aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/atom.names1
-rw-r--r--erts/emulator/beam/beam_emu.c55
-rw-r--r--erts/emulator/beam/bif.c188
-rw-r--r--erts/emulator/beam/bif.tab17
-rw-r--r--erts/emulator/beam/dist.c32
-rw-r--r--erts/emulator/beam/erl_alloc.c6
-rw-r--r--erts/emulator/beam/erl_bif_ddll.c6
-rw-r--r--erts/emulator/beam/erl_bif_timer.c6
-rw-r--r--erts/emulator/beam/erl_bif_trace.c34
-rw-r--r--erts/emulator/beam/erl_db_util.c12
-rw-r--r--erts/emulator/beam/erl_gc.c18
-rw-r--r--erts/emulator/beam/erl_message.c182
-rw-r--r--erts/emulator/beam/erl_message.h13
-rw-r--r--erts/emulator/beam/erl_nif.c6
-rw-r--r--erts/emulator/beam/erl_process.c34
-rw-r--r--erts/emulator/beam/erl_process.h12
-rw-r--r--erts/emulator/beam/erl_trace.c51
-rw-r--r--erts/emulator/beam/io.c30
-rw-r--r--erts/emulator/beam/utils.c6
-rw-r--r--erts/emulator/drivers/common/efile_drv.c488
-rw-r--r--erts/preloaded/ebin/prim_file.beambin46736 -> 38764 bytes
-rw-r--r--erts/preloaded/src/prim_file.erl649
22 files changed, 1254 insertions, 592 deletions
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 7be40976f6..9ce1068b23 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -248,6 +248,7 @@ atom global_heaps_size
atom Gt='>'
atom grun
atom group_leader
+atom have_dt_utag
atom heap_block_size
atom heap_size
atom heap_sizes
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 1dbe2cad00..deeb7357d6 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -1892,23 +1892,52 @@ void process_main(void)
save_calls(c_p, &exp_receive);
}
if (ERL_MESSAGE_TOKEN(msgp) == NIL) {
- SEQ_TRACE_TOKEN(c_p) = NIL;
+#ifdef HAVE_DTRACE
+ if (DT_UTAG(c_p) != NIL) {
+ if (DT_UTAG_FLAGS(c_p) & DT_UTAG_PERMANENT) {
+ SEQ_TRACE_TOKEN(c_p) = am_have_dt_utag;
+ if (DT_UTAG_FLAGS(c_p) & DT_UTAG_SPREADING)
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) stop spreading tag %T with message %T\r\n",c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp));
+ } else {
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) kill tag %T with message %T\r\n",c_p->id,DT_UTAG(c_p),ERL_MESSAGE_TERM(msgp));
+ DT_UTAG(c_p) = NIL;
+ SEQ_TRACE_TOKEN(c_p) = NIL;
+ }
+ } else {
+#endif
+ SEQ_TRACE_TOKEN(c_p) = NIL;
+#ifdef HAVE_DTRACE
+ }
+ DT_UTAG_FLAGS(c_p) &= ~DT_UTAG_SPREADING;
+#endif
} else if (ERL_MESSAGE_TOKEN(msgp) != am_undefined) {
Eterm msg;
SEQ_TRACE_TOKEN(c_p) = ERL_MESSAGE_TOKEN(msgp);
- ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p)));
- ASSERT(SEQ_TRACE_TOKEN_ARITY(c_p) == 5);
- ASSERT(is_small(SEQ_TRACE_TOKEN_SERIAL(c_p)));
- ASSERT(is_small(SEQ_TRACE_TOKEN_LASTCNT(c_p)));
- ASSERT(is_small(SEQ_TRACE_TOKEN_FLAGS(c_p)));
- ASSERT(is_pid(SEQ_TRACE_TOKEN_SENDER(c_p)));
- c_p->seq_trace_lastcnt = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p));
- if (c_p->seq_trace_clock < unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p))) {
- c_p->seq_trace_clock = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p));
+#ifdef HAVE_DTRACE
+ if (ERL_MESSAGE_TOKEN(msgp) == am_have_dt_utag) {
+ if (DT_UTAG(c_p) == NIL) {
+ DT_UTAG(c_p) = ERL_MESSAGE_DT_UTAG(msgp);
+ }
+ DT_UTAG_FLAGS(c_p) |= DT_UTAG_SPREADING;
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) receive tag (%T) with message %T\r\n",c_p->id, DT_UTAG(c_p), ERL_MESSAGE_TERM(msgp));
+ } else {
+#endif
+ ASSERT(is_tuple(SEQ_TRACE_TOKEN(c_p)));
+ ASSERT(SEQ_TRACE_TOKEN_ARITY(c_p) == 5);
+ ASSERT(is_small(SEQ_TRACE_TOKEN_SERIAL(c_p)));
+ ASSERT(is_small(SEQ_TRACE_TOKEN_LASTCNT(c_p)));
+ ASSERT(is_small(SEQ_TRACE_TOKEN_FLAGS(c_p)));
+ ASSERT(is_pid(SEQ_TRACE_TOKEN_SENDER(c_p)));
+ c_p->seq_trace_lastcnt = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p));
+ if (c_p->seq_trace_clock < unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p))) {
+ c_p->seq_trace_clock = unsigned_val(SEQ_TRACE_TOKEN_SERIAL(c_p));
+ }
+ msg = ERL_MESSAGE_TERM(msgp);
+ seq_trace_output(SEQ_TRACE_TOKEN(c_p), msg, SEQ_TRACE_RECEIVE,
+ c_p->id, c_p);
+#ifdef HAVE_DTRACE
}
- msg = ERL_MESSAGE_TERM(msgp);
- seq_trace_output(SEQ_TRACE_TOKEN(c_p), msg, SEQ_TRACE_RECEIVE,
- c_p->id, c_p);
+#endif
}
if (DTRACE_ENABLED(message_receive)) {
Eterm token2 = NIL;
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index ebdca87f4a..6478e54996 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -563,7 +563,11 @@ erts_queue_monitor_message(Process *p,
ref_copy = copy_struct(ref, ref_size, &hp, ohp);
tup = TUPLE5(hp, am_DOWN, ref_copy, type, item_copy, reason_copy);
- erts_queue_message(p, p_locksp, bp, tup, NIL);
+ erts_queue_message(p, p_locksp, bp, tup, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
}
static BIF_RETTYPE
@@ -1944,7 +1948,11 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend) {
if (ERTS_PROC_GET_SAVED_CALLS_BUF(p))
save_calls(p, &exp_send);
- if (SEQ_TRACE_TOKEN(p) != NIL) {
+ if (SEQ_TRACE_TOKEN(p) != NIL
+#ifdef HAVE_DTRACE
+ && SEQ_TRACE_TOKEN(p) != am_have_dt_utag
+#endif
+ ) {
seq_trace_update_send(p);
seq_trace_output(SEQ_TRACE_TOKEN(p), msg,
SEQ_TRACE_SEND, portid, p);
@@ -4226,13 +4234,21 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
for (i = 0; i < erts_max_processes; i++) {
if (process_tab[i] != (Process*) 0) {
Process* p = process_tab[i];
+#ifdef HAVE_DTRACE
+ p->seq_trace_token = (p->dt_utag != NIL) ? am_have_dt_utag : NIL;
+#else
p->seq_trace_token = NIL;
+#endif
p->seq_trace_clock = 0;
p->seq_trace_lastcnt = 0;
ERTS_SMP_MSGQ_MV_INQ2PRIVQ(p);
mp = p->msg.first;
while(mp != NULL) {
+#ifdef HAVE_DTRACE
+ ERL_MESSAGE_TOKEN(mp) = (ERL_MESSAGE_DT_UTAG(mp) != NIL) ? am_have_dt_utag : NIL;
+#else
ERL_MESSAGE_TOKEN(mp) = NIL;
+#endif
mp = mp->next;
}
}
@@ -4630,3 +4646,171 @@ BIF_RETTYPE get_module_info_2(BIF_ALIST_2)
}
BIF_RET(ret);
}
+
+BIF_RETTYPE put_utag_1(BIF_ALIST_1)
+{
+#ifdef HAVE_DTRACE
+ Eterm otag;
+ if (BIF_ARG_1 == am_undefined) {
+ otag = (DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P);
+ DT_UTAG(BIF_P) = NIL;
+ DT_UTAG_FLAGS(BIF_P) = 0;
+ if (SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag) {
+ SEQ_TRACE_TOKEN(BIF_P) = NIL;
+ }
+ BIF_RET(otag);
+ }
+ if (!is_binary(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+ otag = (DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P);
+ DT_UTAG(BIF_P) = BIF_ARG_1;
+ DT_UTAG_FLAGS(BIF_P) |= DT_UTAG_PERMANENT;
+ if (SEQ_TRACE_TOKEN(BIF_P) == NIL) {
+ SEQ_TRACE_TOKEN(BIF_P) = am_have_dt_utag;
+ }
+ BIF_RET(otag);
+#else
+ BIF_RET(am_undefined);
+#endif
+}
+
+BIF_RETTYPE get_utag_0(BIF_ALIST_0)
+{
+#ifdef HAVE_DTRACE
+ BIF_RET((DT_UTAG(BIF_P) == NIL || !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_PERMANENT)) ? am_undefined : DT_UTAG(BIF_P));
+#else
+ BIF_RET(am_undefined);
+#endif
+}
+BIF_RETTYPE get_utag_data_0(BIF_ALIST_0)
+{
+#ifdef HAVE_DTRACE
+ BIF_RET((DT_UTAG(BIF_P) == NIL) ? am_undefined : DT_UTAG(BIF_P));
+#else
+ BIF_RET(am_undefined);
+#endif
+}
+BIF_RETTYPE prepend_vm_utag_data_1(BIF_ALIST_1)
+{
+#ifdef HAVE_DTRACE
+ Eterm b;
+ Eterm *hp;
+ hp = HAlloc(BIF_P,2);
+ if (is_binary((DT_UTAG(BIF_P)))) {
+ Uint sz = binary_size(DT_UTAG(BIF_P));
+ int i;
+ unsigned char *p,*q;
+ byte *temp_alloc = NULL;
+ b = new_binary(BIF_P,NULL,sz+1);
+ q = binary_bytes(b);
+ p = erts_get_aligned_binary_bytes(DT_UTAG(BIF_P),&temp_alloc);
+ for(i=0;i<sz;++i) {
+ q[i] = p[i];
+ }
+ erts_free_aligned_binary_bytes(temp_alloc);
+ q[sz] = '\0';
+ } else {
+ b = new_binary(BIF_P,(byte *)"\0",1);
+ }
+ BIF_RET(CONS(hp,b,BIF_ARG_1));
+#else
+ BIF_RET(BIF_ARG_1);
+#endif
+}
+BIF_RETTYPE append_vm_utag_data_1(BIF_ALIST_1)
+{
+#ifdef HAVE_DTRACE
+ Eterm b;
+ Eterm *hp;
+ hp = HAlloc(BIF_P,2);
+ if (is_binary((DT_UTAG(BIF_P)))) {
+ Uint sz = binary_size(DT_UTAG(BIF_P));
+ int i;
+ unsigned char *p,*q;
+ byte *temp_alloc = NULL;
+ b = new_binary(BIF_P,NULL,sz+1);
+ q = binary_bytes(b);
+ p = erts_get_aligned_binary_bytes(DT_UTAG(BIF_P),&temp_alloc);
+ for(i=0;i<sz;++i) {
+ q[i] = p[i];
+ }
+ erts_free_aligned_binary_bytes(temp_alloc);
+ q[sz] = '\0';
+ } else {
+ b = new_binary(BIF_P,(byte *)"\0",1);
+ }
+ BIF_RET(CONS(hp,BIF_ARG_1,b));
+#else
+ BIF_RET(BIF_ARG_1);
+#endif
+}
+BIF_RETTYPE spread_utag_1(BIF_ALIST_1)
+{
+#ifdef HAVE_DTRACE
+ Eterm ret;
+ Eterm *hp;
+#endif
+ if (BIF_ARG_1 != am_true && BIF_ARG_1 != am_false) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+#ifdef HAVE_DTRACE
+ hp = HAlloc(BIF_P,3);
+ ret = TUPLE2(hp,make_small(DT_UTAG_FLAGS(BIF_P)),DT_UTAG(BIF_P));
+ if (DT_UTAG(BIF_P) != NIL) {
+ if (BIF_ARG_1 == am_true) {
+ DT_UTAG_FLAGS(BIF_P) |= DT_UTAG_SPREADING;
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) start spreading tag %T\r\n",BIF_P->id,DT_UTAG(BIF_P));
+ } else {
+ DT_UTAG_FLAGS(BIF_P) &= ~DT_UTAG_SPREADING;
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) stop spreading tag %T\r\n",BIF_P->id,DT_UTAG(BIF_P));
+ }
+ }
+ BIF_RET(ret);
+#else
+ BIF_RET(am_true);
+#endif
+}
+BIF_RETTYPE restore_utag_1(BIF_ALIST_1)
+{
+#ifdef HAVE_DTRACE
+ Eterm *tpl;
+ Uint x;
+ if (is_not_tuple(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+ tpl = tuple_val(BIF_ARG_1);
+ if(arityval(*tpl) != 2 || is_not_small(tpl[1]) || (is_not_binary(tpl[2]) && tpl[2] != NIL)) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+ if (tpl[2] == NIL) {
+ if (DT_UTAG(BIF_P) != NIL) {
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore Killing tag!\r\n",BIF_P->id);
+ }
+ DT_UTAG(BIF_P) = NIL;
+ if (SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag) {
+ SEQ_TRACE_TOKEN(BIF_P) = NIL;
+ }
+ DT_UTAG_FLAGS(BIF_P) = 0;
+ } else {
+ x = unsigned_val(tpl[1]) & (DT_UTAG_SPREADING | DT_UTAG_PERMANENT);
+ if (!(x & DT_UTAG_SPREADING) && (DT_UTAG_FLAGS(BIF_P) & DT_UTAG_SPREADING)) {
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore stop spreading tag %T\r\n",BIF_P->id,tpl[2]);
+ } else if ((x & DT_UTAG_SPREADING) && !(DT_UTAG_FLAGS(BIF_P) & DT_UTAG_SPREADING)) {
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) restore start spreading tag %T\r\n",BIF_P->id,tpl[2]);
+ }
+ DT_UTAG_FLAGS(BIF_P) = x;
+ DT_UTAG(BIF_P) = tpl[2];
+ if (SEQ_TRACE_TOKEN(BIF_P) == NIL) {
+ SEQ_TRACE_TOKEN(BIF_P) = am_have_dt_utag;
+ }
+ }
+#else
+ if (BIF_ARG_1 != am_true) {
+ BIF_ERROR(BIF_P,BADARG);
+ }
+#endif
+ BIF_RET(am_true);
+}
+
+
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 007c884a6a..7940544156 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -814,6 +814,23 @@ bif erlang:check_old_code/1
#
bif erlang:universaltime_to_posixtime/1
bif erlang:posixtime_to_universaltime/1
+
+#
+# New in R15B01
+#
+
+# The dtrace BIF's are always present, but give dummy results if dynamic trace is not enabled in the build
+bif erlang:put_utag/1
+bif erlang:get_utag/0
+bif erlang:get_utag_data/0
+bif erlang:spread_utag/1
+bif erlang:restore_utag/1
+
+# These are dummies even with enabled dynamic trace unless vm probes are enabled.
+# They are also internal, for dtrace tags sent to the VM's own drivers (efile)
+bif erlang:prepend_vm_utag_data/1
+bif erlang:append_vm_utag_data/1
+
#
# Obsolete
#
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index ba55a1918a..43fc910054 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -382,7 +382,11 @@ static void doit_node_link_net_exits(ErtsLink *lnk, void *vnecp)
Eterm tup;
Eterm *hp = erts_alloc_message_heap(3,&bp,&ohp,rp,&rp_locks);
tup = TUPLE2(hp, am_nodedown, name);
- erts_queue_message(rp, &rp_locks, bp, tup, NIL);
+ erts_queue_message(rp, &rp_locks, bp, tup, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
}
erts_smp_proc_unlock(rp, rp_locks);
}
@@ -750,7 +754,11 @@ erts_dsig_send_msg(ErtsDSigData *dsdp, Eterm remote, Eterm message)
DTRACE_CHARBUF(receiver_name, 64);
UseTmpHeapNoproc(5);
- if (SEQ_TRACE_TOKEN(sender) != NIL) {
+ if (SEQ_TRACE_TOKEN(sender) != NIL
+#ifdef HAVE_DTRACE
+ && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag
+#endif
+ ) {
seq_trace_update_send(sender);
token = SEQ_TRACE_TOKEN(sender);
seq_trace_output(token, message, SEQ_TRACE_SEND, remote, sender);
@@ -799,7 +807,11 @@ erts_dsig_send_reg_msg(ErtsDSigData *dsdp, Eterm remote_name, Eterm message)
DTRACE_CHARBUF(receiver_name, 128);
UseTmpHeapNoproc(6);
- if (SEQ_TRACE_TOKEN(sender) != NIL) {
+ if (SEQ_TRACE_TOKEN(sender) != NIL
+#ifdef HAVE_DTRACE
+ && SEQ_TRACE_TOKEN(sender) != am_have_dt_utag
+#endif
+ ) {
seq_trace_update_send(sender);
token = SEQ_TRACE_TOKEN(sender);
seq_trace_output(token, message, SEQ_TRACE_SEND, remote_name, sender);
@@ -851,7 +863,11 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
DTRACE_CHARBUF(reason_str, 128);
UseTmpHeapNoproc(6);
- if (token != NIL) {
+ if (token != NIL
+#ifdef HAVE_DTRACE
+ && token != am_have_dt_utag
+#endif
+ ) {
seq_trace_update_send(dsdp->proc);
seq_trace_output_exit(token, reason, SEQ_TRACE_SEND, remote, local);
ctl = TUPLE5(&ctl_heap[0],
@@ -866,7 +882,7 @@ erts_dsig_send_exit_tt(ErtsDSigData *dsdp, Eterm local, Eterm remote,
erts_snprintf(remote_name, sizeof(remote_name),
"{%T,%s}", remote, node_name);
erts_snprintf(reason_str, sizeof(reason), "%T", reason);
- if (token != NIL) {
+ if (token != NIL && token != am_have_dt_utag) {
tok_label = signed_val(SEQ_TRACE_T_LABEL(token));
tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token));
tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token));
@@ -3094,7 +3110,11 @@ send_nodes_mon_msg(Process *rp,
}
ASSERT(hend == hp);
- erts_queue_message(rp, rp_locksp, bp, msg, NIL);
+ erts_queue_message(rp, rp_locksp, bp, msg, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
}
static void
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index df27186680..d575e30092 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -3001,7 +3001,11 @@ reply_alloc_info(void *vair)
HRelease(rp, hp_end, hp);
}
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, bp, msg, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
if (air->req_sched == sched_id)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
diff --git a/erts/emulator/beam/erl_bif_ddll.c b/erts/emulator/beam/erl_bif_ddll.c
index 3326fd84df..b58c5ab761 100644
--- a/erts/emulator/beam/erl_bif_ddll.c
+++ b/erts/emulator/beam/erl_bif_ddll.c
@@ -1762,7 +1762,11 @@ static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type,
hp += REF_THING_SIZE;
mess = TUPLE5(hp,type,r,am_driver,driver_name,tag);
}
- erts_queue_message(proc, &rp_locks, bp, mess, am_undefined);
+ erts_queue_message(proc, &rp_locks, bp, mess, am_undefined
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(proc, rp_locks);
ERTS_SMP_CHK_NO_PROC_LOCKS;
}
diff --git a/erts/emulator/beam/erl_bif_timer.c b/erts/emulator/beam/erl_bif_timer.c
index a922a33da3..fbc2f08c09 100644
--- a/erts/emulator/beam/erl_bif_timer.c
+++ b/erts/emulator/beam/erl_bif_timer.c
@@ -373,7 +373,11 @@ bif_timer_timeout(ErtsBifTimer* btm)
message = TUPLE3(hp, am_timeout, ref, message);
}
- erts_queue_message(rp, &rp_locks, bp, message, NIL);
+ erts_queue_message(rp, &rp_locks, bp, message, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
}
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index b0a58c80ea..c518aa6866 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1744,9 +1744,17 @@ Eterm erts_seq_trace(Process *p, Eterm arg1, Eterm arg2,
return THE_NON_VALUE;
}
if (build_result) {
+#ifdef HAVE_DTRACE
+ old_value = (SEQ_TRACE_TOKEN(p) == am_have_dt_utag) ? NIL : SEQ_TRACE_TOKEN(p);
+#else
old_value = SEQ_TRACE_TOKEN(p);
+#endif
}
+#ifdef HAVE_DTRACE
+ SEQ_TRACE_TOKEN(p) = (DT_UTAG(p) != NIL) ? am_have_dt_utag : NIL;
+#else
SEQ_TRACE_TOKEN(p) = NIL;
+#endif
return old_value;
}
else {
@@ -1759,7 +1767,11 @@ new_seq_trace_token(Process* p)
{
Eterm* hp;
- if (SEQ_TRACE_TOKEN(p) == NIL) {
+ if (SEQ_TRACE_TOKEN(p) == NIL
+#ifdef HAVE_DTRACE
+ || SEQ_TRACE_TOKEN(p) == am_have_dt_utag
+#endif
+ ) {
hp = HAlloc(p, 6);
SEQ_TRACE_TOKEN(p) = TUPLE5(hp, make_small(0), /* Flags */
make_small(0), /* Label */
@@ -1779,7 +1791,11 @@ BIF_RETTYPE erl_seq_trace_info(Process *p, Eterm item)
BIF_ERROR(p, BADARG);
}
- if (SEQ_TRACE_TOKEN(p) == NIL) {
+ if (SEQ_TRACE_TOKEN(p) == NIL
+#ifdef HAVE_DTRACE
+ || SEQ_TRACE_TOKEN(p) == am_have_dt_utag
+#endif
+ ) {
if ((item == am_send) || (item == am_receive) ||
(item == am_print) || (item == am_timestamp)) {
hp = HAlloc(p,3);
@@ -1836,8 +1852,13 @@ BIF_RETTYPE seq_trace_info_1(BIF_ALIST_1)
*/
BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1)
{
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL)
+ if (SEQ_TRACE_TOKEN(BIF_P) == NIL
+#ifdef HAVE_DTRACE
+ || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag
+#endif
+ ) {
BIF_RET(am_false);
+ }
seq_trace_update_send(BIF_P);
seq_trace_output(SEQ_TRACE_TOKEN(BIF_P), BIF_ARG_1,
SEQ_TRACE_PRINT, NIL, BIF_P);
@@ -1854,8 +1875,13 @@ BIF_RETTYPE seq_trace_print_1(BIF_ALIST_1)
*/
BIF_RETTYPE seq_trace_print_2(BIF_ALIST_2)
{
- if (SEQ_TRACE_TOKEN(BIF_P) == NIL)
+ if (SEQ_TRACE_TOKEN(BIF_P) == NIL
+#ifdef HAVE_DTRACE
+ || SEQ_TRACE_TOKEN(BIF_P) == am_have_dt_utag
+#endif
+ ) {
BIF_RET(am_false);
+ }
if (!(is_atom(BIF_ARG_1) || is_small(BIF_ARG_1))) {
BIF_ERROR(BIF_P, BADARG);
}
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 4821a7d9fb..eb05ceaaf1 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -2203,7 +2203,11 @@ restart:
*esp++ = am_true;
break;
case matchIsSeqTrace:
- if (SEQ_TRACE_TOKEN(c_p) != NIL)
+ if (SEQ_TRACE_TOKEN(c_p) != NIL
+#ifdef HAVE_DTRACE
+ && SEQ_TRACE_TOKEN(c_p) != am_have_dt_utag
+#endif
+ )
*esp++ = am_true;
else
*esp++ = am_false;
@@ -2227,7 +2231,11 @@ restart:
--esp;
break;
case matchGetSeqToken:
- if (SEQ_TRACE_TOKEN(c_p) == NIL)
+ if (SEQ_TRACE_TOKEN(c_p) == NIL
+#ifdef HAVE_DTRACE
+ || SEQ_TRACE_TOKEN(c_p) == am_have_dt_utag
+#endif
+ )
*esp++ = NIL;
else {
Eterm sender = SEQ_TRACE_TOKEN_SENDER(c_p);
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 679a3645ba..6dfccfe52f 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -1935,7 +1935,13 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset)
roots[n].sz = 1;
n++;
}
-
+#ifdef HAVE_DTRACE
+ if (is_not_immed(p->dt_utag)) {
+ roots[n].v = &p->dt_utag;
+ roots[n].sz = 1;
+ n++;
+ }
+#endif
ASSERT(is_nil(p->tracer_proc) ||
is_internal_pid(p->tracer_proc) ||
is_internal_port(p->tracer_proc));
@@ -2472,6 +2478,13 @@ offset_mqueue(Process *p, Sint offs, char* area, Uint area_size)
if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) {
ERL_MESSAGE_TOKEN(mp) = offset_ptr(mesg, offs);
}
+#ifdef HAVE_DTRACE
+ mesg = ERL_MESSAGE_DT_UTAG(mp);
+ if (is_boxed(mesg) && in_area(ptr_val(mesg), area, area_size)) {
+ ERL_MESSAGE_DT_UTAG(mp) = offset_ptr(mesg, offs);
+ }
+#endif
+
ASSERT((is_nil(ERL_MESSAGE_TOKEN(mp)) ||
is_tuple(ERL_MESSAGE_TOKEN(mp)) ||
is_atom(ERL_MESSAGE_TOKEN(mp))));
@@ -2491,6 +2504,9 @@ offset_one_rootset(Process *p, Sint offs, char* area, Uint area_size,
offset_heap_ptr(&p->fvalue, 1, offs, area, area_size);
offset_heap_ptr(&p->ftrace, 1, offs, area, area_size);
offset_heap_ptr(&p->seq_trace_token, 1, offs, area, area_size);
+#ifdef HAVE_DTRACE
+ offset_heap_ptr(&p->dt_utag, 1, offs, area, area_size);
+#endif
offset_heap_ptr(&p->group_leader, 1, offs, area, area_size);
offset_mqueue(p, offs, area, area_size);
offset_heap_ptr(p->stop, (STACK_START(p) - p->stop), offs, area, area_size);
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 786d6ac52c..dc59b9c2c4 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -393,13 +393,26 @@ erts_queue_dist_message(Process *rcvr,
receiver_name, size_object(msg), rcvr->msg.len,
tok_label, tok_lastcnt, tok_serial);
}
- erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token);
+ erts_queue_message(rcvr, rcvr_locks, mbuf, msg, token
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
}
else {
/* Enqueue message on external format */
ERL_MESSAGE_TERM(mp) = THE_NON_VALUE;
- ERL_MESSAGE_TOKEN(mp) = token;
+#ifdef HAVE_DTRACE
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+ if (token == am_have_dt_utag) {
+ ERL_MESSAGE_TOKEN(mp) = NIL;
+ } else {
+#endif
+ ERL_MESSAGE_TOKEN(mp) = token;
+#ifdef HAVE_DTRACE
+ }
+#endif
mp->next = NULL;
if (DTRACE_ENABLED(message_queued)) {
@@ -431,7 +444,11 @@ erts_queue_message(Process* receiver,
ErtsProcLocks *receiver_locks,
ErlHeapFragment* bp,
Eterm message,
- Eterm seq_trace_token)
+ Eterm seq_trace_token
+#ifdef HAVE_DTRACE
+ , Eterm dt_utag
+#endif
+)
{
ErlMessage* mp;
#ifdef ERTS_SMP
@@ -472,6 +489,9 @@ erts_queue_message(Process* receiver,
ERL_MESSAGE_TERM(mp) = message;
ERL_MESSAGE_TOKEN(mp) = seq_trace_token;
+#ifdef HAVE_DTRACE
+ ERL_MESSAGE_DT_UTAG(mp) = dt_utag;
+#endif
mp->next = NULL;
mp->data.heap_frag = bp;
@@ -547,6 +567,9 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
Sint offs;
Uint sz;
ErlHeapFragment *bp;
+#ifdef HAVE_DTRACE
+ Eterm utag;
+#endif
#ifdef HARD_DEBUG
ProcBin *dbg_mso_start = off_heap->mso;
@@ -556,32 +579,56 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
ErlHeapFragment *dbg_bp;
Uint *dbg_hp, *dbg_thp_start;
Uint dbg_term_sz, dbg_token_sz;
+#ifdef HAVE_DTRACE
+ Eterm dbg_utag;
+ Uint dbg_utag_sz;
+#endif
#endif
bp = msg->data.heap_frag;
term = ERL_MESSAGE_TERM(msg);
token = ERL_MESSAGE_TOKEN(msg);
+#ifdef HAVE_DTRACE
+ utag = ERL_MESSAGE_DT_UTAG(msg);
+#endif
if (!bp) {
+#ifdef HAVE_DTRACE
+ ASSERT(is_immed(term) && is_immed(token) && is_immed(utag));
+#else
ASSERT(is_immed(term) && is_immed(token));
+#endif
return;
}
#ifdef HARD_DEBUG
dbg_term_sz = size_object(term);
dbg_token_sz = size_object(token);
+ dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz);
+#ifdef HAVE_DTRACE
+ dbg_utag_sz = size_object(utag);
+ dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz + dbg_utag_sz );
+#endif
/*ASSERT(dbg_term_sz + dbg_token_sz == erts_msg_used_frag_sz(msg));
Copied size may be smaller due to removed SubBins's or garbage.
Copied size may be larger due to duplicated shared terms.
*/
- dbg_bp = new_message_buffer(dbg_term_sz + dbg_token_sz);
dbg_hp = dbg_bp->mem;
dbg_term = copy_struct(term, dbg_term_sz, &dbg_hp, &dbg_bp->off_heap);
dbg_token = copy_struct(token, dbg_token_sz, &dbg_hp, &dbg_bp->off_heap);
- dbg_thp_start = *hpp;
+#ifdef HAVE_DTRACE
+ dbg_utag = copy_struct(utag, dbg_utag_sz, &dbg_hp, &dbg_bp->off_heap);
+#endif
+ dbg_thp_start = *hpp;
#endif
if (bp->next != NULL) {
- move_multi_frags(hpp, off_heap, bp, msg->m, 2);
+ move_multi_frags(hpp, off_heap, bp, msg->m,
+#ifdef HAVE_DTRACE
+ 3
+#else
+ 2
+#endif
+ );
goto copy_done;
}
@@ -683,6 +730,16 @@ erts_move_msg_mbuf_to_heap(Eterm** hpp, ErlOffHeap* off_heap, ErlMessage *msg)
ASSERT(hp > ptr_val(ERL_MESSAGE_TERM(msg)));
#endif
}
+#ifdef HAVE_DTRACE
+ if (is_not_immed(utag)) {
+ ASSERT(in_heapfrag(ptr_val(utag), bp));
+ ERL_MESSAGE_DT_UTAG(msg) = offset_ptr(utag, offs);
+#ifdef HARD_DEBUG
+ ASSERT(dbg_thp_start <= ptr_val(ERL_MESSAGE_DT_UTAG(msg)));
+ ASSERT(hp > ptr_val(ERL_MESSAGE_DT_UTAG(msg)));
+#endif
+ }
+#endif
copy_done:
@@ -749,6 +806,9 @@ copy_done:
#ifdef HARD_DEBUG
ASSERT(eq(ERL_MESSAGE_TERM(msg), dbg_term));
ASSERT(eq(ERL_MESSAGE_TOKEN(msg), dbg_token));
+#ifdef HAVE_DTRACE
+ ASSERT(eq(ERL_MESSAGE_DT_UTAG(msg), dbg_utag));
+#endif
free_message_buffer(dbg_bp);
#endif
@@ -841,42 +901,85 @@ erts_send_message(Process* sender,
}
if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) {
Eterm* hp;
+ Eterm stoken = SEQ_TRACE_TOKEN(sender);
+ Uint seq_trace_size = 0;
+#ifdef HAVE_DTRACE
+ Uint dt_utag_size = 0;
+ Eterm utag = NIL;
+#endif
- BM_SWAP_TIMER(send,size);
+ BM_SWAP_TIMER(send,size);
msize = size_object(message);
- BM_SWAP_TIMER(size,send);
+ BM_SWAP_TIMER(size,send);
+
+#ifdef HAVE_DTRACE
+ if (stoken != am_have_dt_utag) {
+#endif
- seq_trace_update_send(sender);
- seq_trace_output(SEQ_TRACE_TOKEN(sender), message, SEQ_TRACE_SEND,
- receiver->id, sender);
- bp = new_message_buffer(msize + 6 /* TUPLE5 */);
+ seq_trace_update_send(sender);
+ seq_trace_output(stoken, message, SEQ_TRACE_SEND,
+ receiver->id, sender);
+ seq_trace_size = 6; /* TUPLE5 */
+#ifdef HAVE_DTRACE
+ }
+ if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
+ dt_utag_size = size_object(DT_UTAG(sender));
+ } else if (stoken == am_have_dt_utag ) {
+ stoken = NIL;
+ }
+#endif
+
+ bp = new_message_buffer(msize + seq_trace_size
+#ifdef HAVE_DTRACE
+ + dt_utag_size
+#endif
+ );
hp = bp->mem;
BM_SWAP_TIMER(send,copy);
- token = copy_struct(SEQ_TRACE_TOKEN(sender),
- 6 /* TUPLE5 */,
+ token = copy_struct(stoken,
+ seq_trace_size,
&hp,
&bp->off_heap);
message = copy_struct(message, msize, &hp, &bp->off_heap);
+#ifdef HAVE_DTRACE
+ if (DT_UTAG_FLAGS(sender) & DT_UTAG_SPREADING) {
+ utag = copy_struct(DT_UTAG(sender), dt_utag_size, &hp, &bp->off_heap);
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) Spreading tag (%T) with message %T!\r\n",sender->id, utag, message);
+ }
+#if 0
+ DT_UTAG_FLAGS(sender) &= ~DT_UTAG_SPREADING;
+ if (!(DT_UTAG_FLAGS(sender) & DT_UTAG_PERMANENT)) {
+ erts_fprintf(stderr,"XXX: PaN: Dtrace -> (%T) Killing tag!\r\n",sender->id);
+ DT_UTAG(sender) = NIL;
+ if (SEQ_TRACE_TOKEN(sender) == am_have_dt_utag) {
+ SEQ_TRACE_TOKEN(sender) = NIL;
+ }
+ }
+#endif
+#endif
BM_MESSAGE_COPIED(msize);
BM_SWAP_TIMER(copy,send);
if (DTRACE_ENABLED(message_send)) {
- Eterm token2 = NIL;
-
- token2 = SEQ_TRACE_TOKEN(sender);
- tok_label = signed_val(SEQ_TRACE_T_LABEL(token2));
- tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(token2));
- tok_serial = signed_val(SEQ_TRACE_T_SERIAL(token2));
- DTRACE6(message_send, sender_name, receiver_name,
- msize, tok_label, tok_lastcnt, tok_serial);
+ if (stoken != NIL) {
+ tok_label = signed_val(SEQ_TRACE_T_LABEL(stoken));
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(stoken));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(stoken));
+ }
+ DTRACE6(message_send, sender_name, receiver_name,
+ msize, tok_label, tok_lastcnt, tok_serial);
}
erts_queue_message(receiver,
receiver_locks,
bp,
message,
- token);
+ token
+#ifdef HAVE_DTRACE
+ , utag
+#endif
+ );
BM_SWAP_TIMER(send,system);
#ifdef HYBRID
} else {
@@ -909,6 +1012,9 @@ erts_send_message(Process* sender,
size_object(message)msize, tok_label, tok_lastcnt, tok_serial);
ERL_MESSAGE_TERM(mp) = message;
ERL_MESSAGE_TOKEN(mp) = NIL;
+#ifdef HAVE_DTRACE
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+#endif
mp->next = NULL;
LINK_MESSAGE(receiver, mp);
ACTIVATE(receiver);
@@ -951,6 +1057,9 @@ erts_send_message(Process* sender,
mp->data.attached = NULL;
ERL_MESSAGE_TERM(mp) = message;
ERL_MESSAGE_TOKEN(mp) = NIL;
+#ifdef HAVE_DTRACE
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+#endif
mp->next = NULL;
/*
* We move 'in queue' to 'private queue' and place
@@ -984,7 +1093,11 @@ erts_send_message(Process* sender,
BM_SWAP_TIMER(copy,send);
DTRACE6(message_send, sender_name, receiver_name,
msize, tok_label, tok_lastcnt, tok_serial);
- erts_queue_message(receiver, receiver_locks, bp, message, token);
+ erts_queue_message(receiver, receiver_locks, bp, message, token
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
BM_SWAP_TIMER(send,system);
#else
ErlMessage* mp = message_alloc();
@@ -1008,6 +1121,9 @@ erts_send_message(Process* sender,
(uint32_t)msize, tok_label, tok_lastcnt, tok_serial);
ERL_MESSAGE_TERM(mp) = message;
ERL_MESSAGE_TOKEN(mp) = NIL;
+#ifdef HAVE_DTRACE
+ ERL_MESSAGE_DT_UTAG(mp) = NIL;
+#endif
mp->next = NULL;
mp->data.attached = NULL;
LINK_MESSAGE(receiver, mp);
@@ -1046,7 +1162,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp,
Eterm temptoken;
ErlHeapFragment* bp = NULL;
- if (token != NIL) {
+ if (token != NIL
+#ifdef HAVE_DTRACE
+ && token != am_have_dt_utag
+#endif
+ ) {
ASSERT(is_tuple(token));
sz_reason = size_object(reason);
@@ -1061,7 +1181,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp,
/* the trace token must in this case be updated by the caller */
seq_trace_output(token, save, SEQ_TRACE_SEND, to->id, NULL);
temptoken = copy_struct(token, sz_token, &hp, &bp->off_heap);
- erts_queue_message(to, to_locksp, bp, save, temptoken);
+ erts_queue_message(to, to_locksp, bp, save, temptoken
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
} else {
ErlOffHeap *ohp;
sz_reason = size_object(reason);
@@ -1078,7 +1202,11 @@ erts_deliver_exit_message(Eterm from, Process *to, ErtsProcLocks *to_locksp,
? from
: copy_struct(from, sz_from, &hp, ohp));
save = TUPLE3(hp, am_EXIT, from_copy, mess);
- erts_queue_message(to, to_locksp, bp, save, NIL);
+ erts_queue_message(to, to_locksp, bp, save, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
}
}
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index 5aca0db6fe..98321dd2c6 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -70,11 +70,18 @@ typedef struct erl_mesg {
ErlHeapFragment *heap_frag;
void *attached;
} data;
+#ifdef HAVE_DTRACE
+ Eterm m[3]; /* m[0] = message, m[1] = seq trace token, m[3] = dynamic trace user tag */
+#else
Eterm m[2]; /* m[0] = message, m[1] = seq trace token */
+#endif
} ErlMessage;
#define ERL_MESSAGE_TERM(mp) ((mp)->m[0])
#define ERL_MESSAGE_TOKEN(mp) ((mp)->m[1])
+#ifdef HAVE_DTRACE
+#define ERL_MESSAGE_DT_UTAG(mp) ((mp)->m[2])
+#endif
/* Size of default message buffer (erl_message.c) */
#define ERL_MESSAGE_BUF_SZ 500
@@ -221,7 +228,11 @@ ErlHeapFragment* erts_resize_message_buffer(ErlHeapFragment *, Uint,
Eterm *, Uint);
void free_message_buffer(ErlHeapFragment *);
void erts_queue_dist_message(Process*, ErtsProcLocks*, ErtsDistExternal *, Eterm);
-void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*, Eterm, Eterm);
+void erts_queue_message(Process*, ErtsProcLocks*, ErlHeapFragment*, Eterm, Eterm
+#ifdef HAVE_DTRACE
+ , Eterm dt_utag
+#endif
+);
void erts_deliver_exit_message(Eterm, Process*, ErtsProcLocks *, Eterm, Eterm);
void erts_send_message(Process*, Process*, ErtsProcLocks*, Eterm, unsigned);
void erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp);
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index dc4049327d..ebc771b016 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -351,7 +351,11 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
if (flush_me) {
flush_env(env); /* Needed for ERTS_HOLE_CHECK */
}
- erts_queue_message(rp, &rp_locks, frags, msg, am_undefined);
+ erts_queue_message(rp, &rp_locks, frags, msg, am_undefined
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
if (rp_locks) {
ERTS_SMP_LC_ASSERT(rp_locks == (rp_had_locks | (ERTS_PROC_LOCK_MSGQ |
ERTS_PROC_LOCK_STATUS)));
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 1173624f51..6771e00c7e 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -679,7 +679,11 @@ reply_sched_wall_time(void *vswtrp)
hpp = &hp;
}
- erts_queue_message(rp, &rp_locks, bp, msg, NIL);
+ erts_queue_message(rp, &rp_locks, bp, msg, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
if (swtrp->req_sched == esdp->no)
rp_locks &= ~ERTS_PROC_LOCK_MAIN;
@@ -7260,6 +7264,10 @@ erl_create_process(Process* parent, /* Parent of process (default group leader).
p->seq_trace_lastcnt = 0;
p->seq_trace_clock = 0;
SEQ_TRACE_TOKEN(p) = NIL;
+#ifdef HAVE_DTRACE
+ DT_UTAG(p) = NIL;
+ DT_UTAG_FLAGS(p) = 0;
+#endif
p->parent = parent->id == ERTS_INVALID_PID ? NIL : parent->id;
#ifdef HYBRID
@@ -7851,7 +7859,11 @@ static ERTS_INLINE void
send_exit_message(Process *to, ErtsProcLocks *to_locksp,
Eterm exit_term, Uint term_size, Eterm token)
{
- if (token == NIL) {
+ if (token == NIL
+#ifdef HAVE_DTRACE
+ || token == am_have_dt_utag
+#endif
+ ) {
Eterm* hp;
Eterm mess;
ErlHeapFragment* bp;
@@ -7859,7 +7871,11 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp,
hp = erts_alloc_message_heap(term_size, &bp, &ohp, to, to_locksp);
mess = copy_struct(exit_term, term_size, &hp, ohp);
- erts_queue_message(to, to_locksp, bp, mess, NIL);
+ erts_queue_message(to, to_locksp, bp, mess, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
} else {
ErlHeapFragment* bp;
Eterm* hp;
@@ -7875,7 +7891,11 @@ send_exit_message(Process *to, ErtsProcLocks *to_locksp,
/* the trace token must in this case be updated by the caller */
seq_trace_output(token, mess, SEQ_TRACE_SEND, to->id, NULL);
temp_token = copy_struct(token, sz_token, &hp, &bp->off_heap);
- erts_queue_message(to, to_locksp, bp, mess, temp_token);
+ erts_queue_message(to, to_locksp, bp, mess, temp_token
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
}
}
@@ -7981,7 +8001,11 @@ send_exit_signal(Process *c_p, /* current process if and only
if (ERTS_PROC_IS_TRAPPING_EXITS(rp)
&& (reason != am_kill || (flags & ERTS_XSIG_FLG_IGN_KILL))) {
- if (is_not_nil(token) && token_update)
+ if (is_not_nil(token)
+#ifdef HAVE_DTRACE
+ && token != am_have_dt_utag
+#endif
+ && token_update)
seq_trace_update_send(token_update);
if (is_value(exit_tuple))
send_exit_message(rp, rp_locks, exit_tuple, exit_tuple_sz, token);
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index d671638ce8..35b31b1009 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -683,6 +683,10 @@ struct process {
Uint seq_trace_lastcnt;
Eterm seq_trace_token; /* Sequential trace token (tuple size 5 see below) */
+#ifdef HAVE_DTRACE
+ Eterm dt_utag; /* Place to store the dynamc trace user tag */
+ Uint dt_utag_flags; /* flag field for the dt_utag */
+#endif
BeamInstr initial[3]; /* Initial module(0), function(1), arity(2), often used instead
of pointer to funcinfo instruction, hence the BeamInstr datatype */
BeamInstr* current; /* Current Erlang function, part of the funcinfo:
@@ -998,6 +1002,14 @@ extern struct erts_system_profile_flags_t erts_system_profile_flags;
#define SEQ_TRACE_PRINT (1 << 2)
#define SEQ_TRACE_TIMESTAMP (1 << 3)
+#ifdef HAVE_DTRACE
+#define DT_UTAG_PERMANENT (1 << 0)
+#define DT_UTAG_SPREADING (1 << 1)
+#define DT_UTAG(P) ((P)->dt_utag)
+#define DT_UTAG_FLAGS(P) ((P)->dt_utag_flags)
+#endif
+
+
#ifdef ERTS_SMP
/* Status flags ... */
#define ERTS_PROC_SFLG_PENDADD2SCHEDQ (((Uint32) 1) << 0) /* Pending
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index b1d1e1d9b0..a4aed0122b 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -125,8 +125,13 @@ do { \
enqueue_sys_msg_unlocked(SYS_MSG_TYPE_TRACE, (FPID), (TPID), (MSG), (BP)); \
} while(0)
#else
+#ifdef HAVE_DTRACE
#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \
- erts_queue_message((TPROC), NULL, (BP), (MSG), NIL)
+ erts_queue_message((TPROC), NULL, (BP), (MSG), NIL, NIL)
+#else
+#define ERTS_ENQ_TRACE_MSG(FPID, TPROC, MSG, BP) \
+ erts_queue_message((TPROC), NULL, (BP), (MSG), NIL)
+#endif
#endif
/*
@@ -583,7 +588,11 @@ profile_send(Eterm from, Eterm message) {
hp = erts_alloc_message_heap(sz, &bp, &off_heap, profile_p, 0);
msg = copy_struct(message, sz, &hp, &bp->off_heap);
- erts_queue_message(profile_p, NULL, bp, msg, NIL);
+ erts_queue_message(profile_p, NULL, bp, msg, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
}
}
@@ -994,9 +1003,13 @@ seq_trace_update_send(Process *p)
{
Eterm seq_tracer = erts_get_system_seq_tracer();
ASSERT((is_tuple(SEQ_TRACE_TOKEN(p)) || is_nil(SEQ_TRACE_TOKEN(p))));
- if ( (p->id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL))
+ if ( (p->id == seq_tracer) || (SEQ_TRACE_TOKEN(p) == NIL)
+#ifdef HAVE_DTRACE
+ || (SEQ_TRACE_TOKEN(p) == am_have_dt_utag)
+#endif
+ ) {
return 0;
-
+ }
SEQ_TRACE_TOKEN_SENDER(p) = p->id; /* Internal pid */
SEQ_TRACE_TOKEN_SERIAL(p) =
make_small(++(p -> seq_trace_clock));
@@ -1178,7 +1191,11 @@ seq_trace_output_generic(Eterm token, Eterm msg, Uint type,
enqueue_sys_msg_unlocked(SYS_MSG_TYPE_SEQTRACE, NIL, NIL, mess, bp);
erts_smp_mtx_unlock(&smq_mtx);
#else
- erts_queue_message(tracer, NULL, bp, mess, NIL); /* trace_token must be NIL here */
+ erts_queue_message(tracer, NULL, bp, mess, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ ); /* trace_token must be NIL here */
#endif
}
}
@@ -2469,7 +2486,11 @@ monitor_long_gc(Process *p, Uint time) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ erts_queue_message(monitor_p, NULL, bp, msg, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
#endif
}
@@ -2541,7 +2562,11 @@ monitor_large_heap(Process *p) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ erts_queue_message(monitor_p, NULL, bp, msg, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
#endif
}
@@ -2571,7 +2596,11 @@ monitor_generic(Process *p, Eterm type, Eterm spec) {
#ifdef ERTS_SMP
enqueue_sys_msg(SYS_MSG_TYPE_SYSMON, p->id, NIL, msg, bp);
#else
- erts_queue_message(monitor_p, NULL, bp, msg, NIL);
+ erts_queue_message(monitor_p, NULL, bp, msg, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
#endif
}
@@ -3357,7 +3386,11 @@ sys_msg_dispatcher_func(void *unused)
}
else {
queue_proc_msg:
- erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL);
+ erts_queue_message(proc,&proc_locks,smqp->bp,smqp->msg,NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
#ifdef DEBUG_PRINTOUTS
erts_fprintf(stderr, "delivered\n");
#endif
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 81f79b8f85..75ea53c2b7 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -1564,7 +1564,11 @@ deliver_result(Eterm sender, Eterm pid, Eterm res)
hp = erts_alloc_message_heap(sz_res + 3, &bp, &ohp, rp, &rp_locks);
res = copy_struct(res, sz_res, &hp, ohp);
tuple = TUPLE2(hp, sender, res);
- erts_queue_message(rp, &rp_locks, bp, tuple, NIL);
+ erts_queue_message(rp, &rp_locks, bp, tuple, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
}
@@ -1653,7 +1657,11 @@ static void deliver_read_message(Port* prt, Eterm to,
tuple = TUPLE2(hp, prt->id, tuple);
hp += 3;
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
}
@@ -1806,7 +1814,11 @@ deliver_vec_message(Port* prt, /* Port */
tuple = TUPLE2(hp, prt->id, tuple);
hp += 3;
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
}
@@ -2772,7 +2784,11 @@ void driver_report_exit(int ix, int status)
hp += 3;
tuple = TUPLE2(hp, prt->id, tuple);
- erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined);
+ erts_queue_message(rp, &rp_locks, bp, tuple, am_undefined
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
erts_smp_proc_unlock(rp, rp_locks);
erts_smp_proc_dec_refc(rp);
@@ -3322,7 +3338,11 @@ driver_deliver_term(ErlDrvPort port,
HRelease(rp, hp_end, hp);
}
/* send message */
- erts_queue_message(rp, &rp_locks, bp, mess, am_undefined);
+ erts_queue_message(rp, &rp_locks, bp, mess, am_undefined
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
}
else {
if (b2t.ix > b2t.used)
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 49b6618f73..2efcd19162 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -1697,7 +1697,11 @@ static int do_send_to_logger(Eterm tag, Eterm gleader, char *buf, int len)
erts_queue_error_logger_message(from, tuple3, bp);
}
#else
- erts_queue_message(p, NULL /* only used for smp build */, bp, tuple3, NIL);
+ erts_queue_message(p, NULL /* only used for smp build */, bp, tuple3, NIL
+#ifdef HAVE_DTRACE
+ , NIL
+#endif
+ );
#endif
return 0;
}
diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c
index 293f024e45..62b582f76a 100644
--- a/erts/emulator/drivers/common/efile_drv.c
+++ b/erts/emulator/drivers/common/efile_drv.c
@@ -100,7 +100,7 @@
#endif
#include <stdlib.h>
-// Need (NON)BLOCKING macros for sendfile
+/* Need (NON)BLOCKING macros for sendfile */
#ifndef WANT_NONBLOCKING
#define WANT_NONBLOCKING
#endif
@@ -112,7 +112,7 @@
#include "erl_threads.h"
#include "zlib.h"
#include "gzio.h"
-#include "dtrace-wrapper.h"
+#include "dtrace-wrapper.h"
#include <ctype.h>
#include <sys/types.h>
@@ -149,10 +149,6 @@ typedef struct {
dt_private *get_dt_private(int);
#else /* HAVE_DTRACE */
-typedef struct {
- char dummy; /* Unused except to quiet some compilers */
-} dt_private;
-
#define DTRACE_INVOKE_SETUP(op) do {} while (0)
#define DTRACE_INVOKE_SETUP_BY_NAME(op) do {} while (0)
#define DTRACE_INVOKE_RETURN(op) do {} while (0)
@@ -212,6 +208,9 @@ typedef struct {
#ifdef FILENAMES_16BIT
+#ifdef HAVE_DTRACE
+#error 16bit characters in filenames and dtrace in combination is not supported.
+#endif
# define FILENAME_BYTELEN(Str) filename_len_16bit(Str)
# define FILENAME_COPY(To,From) filename_cpy_16bit((To),(From))
# define FILENAME_CHARSIZE 2
@@ -432,8 +431,6 @@ struct t_data
int sched_i1;
Uint64 sched_i2;
char sched_utag[DTRACE_EFILE_BUFSIZ+1];
-#else
- char sched_utag[1];
#endif
int result_ok;
Efile_error errInfo;
@@ -2027,8 +2024,11 @@ static void cq_execute(file_descriptor *desc) {
}
static struct t_data *async_write(file_descriptor *desc, int *errp,
- int reply, Uint32 reply_size,
- Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3) {
+ int reply, Uint32 reply_size
+#ifdef HAVE_DTRACE
+ ,Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3
+#endif
+) {
struct t_data *d;
if (! (d = EF_ALLOC(sizeof(struct t_data) - 1))) {
if (errp) *errp = ENOMEM;
@@ -2041,11 +2041,13 @@ static struct t_data *async_write(file_descriptor *desc, int *errp,
d->c.writev.port = desc->port;
d->c.writev.q_mtx = desc->q_mtx;
d->c.writev.size = desc->write_buffered;
+#ifdef HAVE_DTRACE
if (dt_i1 != NULL) {
*dt_i1 = d->fd;
*dt_i2 = d->flags;
*dt_i3 = d->c.writev.size;
}
+#endif
d->reply = reply;
d->c.writev.free_size = 0;
d->c.writev.reply_size = reply_size;
@@ -2057,16 +2059,24 @@ static struct t_data *async_write(file_descriptor *desc, int *errp,
return d;
}
-static int flush_write(file_descriptor *desc, int *errp,
- dt_private *dt_priv, char *dt_utag) {
+static int flush_write(file_descriptor *desc, int *errp
+#ifdef HAVE_DTRACE
+ , dt_private *dt_priv, char *dt_utag
+#endif
+) {
int result = 0;
+#ifdef HAVE_DTRACE
Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0;
+#endif
struct t_data *d = NULL;
MUTEX_LOCK(desc->q_mtx);
if (desc->write_buffered > 0) {
- if ((d = async_write(desc, errp, 0, 0,
- &dt_i1, &dt_i2, &dt_i3)) == NULL) {
+ if ((d = async_write(desc, errp, 0, 0
+#ifdef HAVE_DTRACE
+ ,&dt_i1, &dt_i2, &dt_i3
+#endif
+ )) == NULL) {
result = -1;
}
}
@@ -2101,10 +2111,17 @@ static int check_write_error(file_descriptor *desc, int *errp) {
return 0;
}
-static int flush_write_check_error(file_descriptor *desc, int *errp,
- dt_private *dt_priv, char *dt_utag) {
+static int flush_write_check_error(file_descriptor *desc, int *errp
+#ifdef HAVE_DTRACE
+ , dt_private *dt_priv, char *dt_utag
+#endif
+ ) {
int r;
- if ( (r = flush_write(desc, errp, dt_priv, dt_utag)) != 0) {
+ if ( (r = flush_write(desc, errp
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ )) != 0) {
check_write_error(desc, NULL);
return r;
} else {
@@ -2113,8 +2130,11 @@ static int flush_write_check_error(file_descriptor *desc, int *errp,
}
static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply,
- Sint64 offset, int origin,
- Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3) {
+ Sint64 offset, int origin
+#ifdef HAVE_DTRACE
+ , Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3
+#endif
+ ) {
struct t_data *d;
if (! (d = EF_ALLOC(sizeof(struct t_data)))) {
*errp = ENOMEM;
@@ -2126,11 +2146,13 @@ static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply,
d->reply = reply;
d->c.lseek.offset = offset;
d->c.lseek.origin = origin;
+#ifdef HAVE_DTRACE
if (dt_i1 != NULL) {
*dt_i1 = d->fd;
*dt_i2 = d->c.lseek.offset;
*dt_i3 = d->c.lseek.origin;
}
+#endif
d->invoke = invoke_lseek;
d->free = free_data;
d->level = 1;
@@ -2147,18 +2169,26 @@ static void flush_read(file_descriptor *desc) {
}
}
-static int lseek_flush_read(file_descriptor *desc, int *errp,
- dt_private *dt_priv, char *dt_utag) {
+static int lseek_flush_read(file_descriptor *desc, int *errp
+#ifdef HAVE_DTRACE
+ ,dt_private *dt_priv, char *dt_utag
+#endif
+ ) {
int r = 0;
size_t read_size = desc->read_size;
+#ifdef HAVE_DTRACE
Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0;
+#endif
struct t_data *d;
flush_read(desc);
if (read_size != 0) {
if ((d = async_lseek(desc, errp, 0,
- -((ssize_t)read_size), EFILE_SEEK_CUR,
- &dt_i1, &dt_i2, &dt_i3)) == NULL) {
+ -((ssize_t)read_size), EFILE_SEEK_CUR
+#ifdef HAVE_DTRACE
+ , &dt_i1, &dt_i2, &dt_i3
+#endif
+ )) == NULL) {
r = -1;
} else {
#ifdef HAVE_DTRACE
@@ -2490,13 +2520,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
char* name; /* Points to the filename in buf. */
int command;
struct t_data *d = NULL;
- ERTS_DECLARE_DUMMY(char *dt_utag) = NULL;
- char *dt_s1 = NULL, *dt_s2 = NULL;
- ERTS_DECLARE_DUMMY(Sint64 dt_i1) = 0;
- ERTS_DECLARE_DUMMY(Sint64 dt_i2) = 0;
- ERTS_DECLARE_DUMMY(Sint64 dt_i3) = 0;
- ERTS_DECLARE_DUMMY(Sint64 dt_i4) = 0;
#ifdef HAVE_DTRACE
+ char *dt_utag = NULL;
+ char *dt_s1 = NULL, *dt_s2 = NULL;
+ Sint64 dt_i1 = 0;
+ Sint64 dt_i2 = 0;
+ Sint64 dt_i3 = 0;
+ Sint64 dt_i4 = 0;
dt_private *dt_priv = get_dt_private(0);
#endif /* HAVE_DTRACE */
@@ -2513,8 +2543,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef HAVE_DTRACE
dt_s1 = d->b;
- dt_utag = name + strlen(d->b) + 1;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_mkdir;
d->free = free_data;
@@ -2526,8 +2558,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef HAVE_DTRACE
dt_s1 = d->b;
- dt_utag = name + strlen(d->b) + 1;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_rmdir;
d->free = free_data;
@@ -2539,8 +2573,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef HAVE_DTRACE
dt_s1 = d->b;
- dt_utag = name + strlen(d->b) + 1;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_delete_file;
d->free = free_data;
@@ -2557,10 +2593,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
+ FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
- dt_s1 = d->b;
FILENAME_COPY(d->b + namelen, new_name);
+#ifdef HAVE_DTRACE
+ dt_s1 = d->b;
dt_s2 = d->b + namelen;
- dt_utag = buf + namelen + strlen(dt_s2) + 1;
+ dt_utag = buf + namelen + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->flags = desc->flags;
d->fd = fd;
d->command = command;
@@ -2574,8 +2612,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef HAVE_DTRACE
dt_s1 = d->b;
- dt_utag = name + strlen(d->b) + 1;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_chdir;
d->free = free_data;
@@ -2587,7 +2627,9 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1);
d->drive = *(uchar*)buf;
+#ifdef HAVE_DTRACE
dt_utag = buf + 1;
+#endif
d->command = command;
d->invoke = invoke_pwd;
d->free = free_data;
@@ -2603,8 +2645,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
+#ifdef HAVE_DTRACE
dt_s1 = d->b;
- dt_utag = name + strlen(d->b) + 1;
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
d->dir_handle = NULL;
d->command = command;
d->invoke = invoke_readdir;
@@ -2629,9 +2673,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
dir_handle = NULL;
resbuf[0] = FILE_RESP_LFNAME;
+#ifdef HAVE_DTRACE
dt_s1 = name;
- dt_utag = name + strlen(dt_s1) + 1;
-
+ dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE;
+#endif
/* Fill the buffer with multiple directory listings before sending it to the
* receiving process. READDIR_CHUNKS is minimum number of files sent to the
* receiver.
@@ -2680,11 +2725,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
FILENAME_CHARSIZE);
d->flags = get_int32((uchar*)buf);
- dt_i1 = d->flags;
name = buf+4;
FILENAME_COPY(d->b, name);
+#ifdef HAVE_DTRACE
+ dt_i1 = d->flags;
dt_s1 = d->b;
- dt_utag = name + strlen(d->b) + 1;
+ dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_open;
d->free = free_data;
@@ -2696,9 +2743,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
{
d = EF_SAFE_ALLOC(sizeof(struct t_data));
- dt_utag = name;
d->fd = fd;
+#ifdef HAVE_DTRACE
+ dt_utag = name;
dt_i1 = fd;
+#endif
d->command = command;
d->invoke = invoke_fdatasync;
d->free = free_data;
@@ -2710,9 +2759,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
{
d = EF_SAFE_ALLOC(sizeof(struct t_data));
- dt_utag = name;
d->fd = fd;
+#ifdef HAVE_DTRACE
+ dt_utag = name;
dt_i1 = fd;
+#endif
d->command = command;
d->invoke = invoke_fsync;
d->free = free_data;
@@ -2728,13 +2779,15 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
- dt_utag = name + strlen(d->b) + 1;
d->fd = fd;
+#ifdef HAVE_DTRACE
+ dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
if (command == FILE_LSTAT) {
dt_s1 = d->b;
} else {
dt_i1 = fd;
}
+#endif
d->command = command;
d->invoke = invoke_flstat;
d->free = free_data;
@@ -2746,11 +2799,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
{
d = EF_SAFE_ALLOC(sizeof(struct t_data));
- dt_utag = name;
d->flags = desc->flags;
d->fd = fd;
+#ifdef HAVE_DTRACE
+ dt_utag = name;
dt_i1 = fd;
dt_i2 = d->flags;
+#endif
d->command = command;
d->invoke = invoke_truncate;
d->free = free_data;
@@ -2764,18 +2819,20 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
+ FILENAME_BYTELEN(buf + 9*4) + FILENAME_CHARSIZE);
d->info.mode = get_int32(buf + 0 * 4);
- dt_i1 = d->info.mode;
d->info.uid = get_int32(buf + 1 * 4);
- dt_i2 = d->info.uid;
d->info.gid = get_int32(buf + 2 * 4);
- dt_i3 = d->info.gid;
d->info.accessTime = (time_t)((Sint64)get_int64(buf + 3 * 4));
d->info.modifyTime = (time_t)((Sint64)get_int64(buf + 5 * 4));
d->info.cTime = (time_t)((Sint64)get_int64(buf + 7 * 4));
FILENAME_COPY(d->b, buf + 9*4);
+#ifdef HAVE_DTRACE
+ dt_i1 = d->info.mode;
+ dt_i2 = d->info.uid;
+ dt_i3 = d->info.gid;
dt_s1 = d->b;
- dt_utag = buf + 9 * 4 + strlen(d->b) + 1;
+ dt_utag = buf + 9 * 4 + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_write_info;
d->free = free_data;
@@ -2788,8 +2845,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1);
FILENAME_COPY(d->b, name);
+#ifdef HAVE_DTRACE
dt_s1 = d->b;
- dt_utag = name + strlen(d->b) + 1;
+ dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_readlink;
d->free = free_data;
@@ -2801,8 +2860,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
{
d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1);
FILENAME_COPY(d->b, name);
+#ifdef HAVE_DTRACE
dt_s1 = d->b;
- dt_utag = name + strlen(d->b) + 1;
+ dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE;
+#endif
d->command = command;
d->invoke = invoke_altname;
d->free = free_data;
@@ -2822,10 +2883,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
+ FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
- dt_s1 = d->b;
FILENAME_COPY(d->b + namelen, new_name);
+#ifdef HAVE_DTRACE
+ dt_s1 = d->b;
dt_s2 = d->b + namelen;
- dt_utag = buf + namelen + strlen(dt_s2) + 1;
+ dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE;
+#endif
d->flags = desc->flags;
d->fd = fd;
d->command = command;
@@ -2846,10 +2909,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
+ FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE);
FILENAME_COPY(d->b, name);
- dt_s1 = d->b;
FILENAME_COPY(d->b + namelen, new_name);
+#ifdef HAVE_DTRACE
+ dt_s1 = d->b;
dt_s2 = d->b + namelen;
- dt_utag = buf + namelen + strlen(dt_s2) + 1;
+ dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE;
+#endif
d->flags = desc->flags;
d->fd = fd;
d->command = command;
@@ -2864,18 +2929,20 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count)
d = EF_SAFE_ALLOC(sizeof(struct t_data));
d->fd = fd;
- dt_i1 = d->fd;
d->command = command;
d->invoke = invoke_fadvise;
d->free = free_data;
d->level = 2;
d->c.fadvise.offset = get_int64((uchar*) buf);
- dt_i2 = d->c.fadvise.offset;
d->c.fadvise.length = get_int64(((uchar*) buf) + sizeof(Sint64));
- dt_i3 = d->c.fadvise.length;
d->c.fadvise.advise = get_int32(((uchar*) buf) + 2 * sizeof(Sint64));
+#ifdef HAVE_DTRACE
+ dt_i1 = d->fd;
+ dt_i2 = d->c.fadvise.offset;
+ dt_i3 = d->c.fadvise.length;
dt_i4 = d->c.fadvise.advise;
dt_utag = buf + 3 * sizeof(Sint64);
+#endif
goto done;
}
@@ -2920,8 +2987,6 @@ file_flush(ErlDrvData e) {
#endif
#ifdef HAVE_DTRACE
dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base);
-#else
- dt_private *dt_priv = NULL;
#endif
TRACE_C('f');
@@ -2933,8 +2998,11 @@ file_flush(ErlDrvData e) {
#ifdef DEBUG
r =
#endif
- flush_write(desc, NULL, dt_priv,
- (desc->d == NULL) ? NULL : desc->d->sched_utag);
+ flush_write(desc, NULL
+#ifdef HAVE_DTRACE
+ , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag
+#endif
+ );
/* Only possible reason for bad return value is ENOMEM, and
* there is nobody to tell...
*/
@@ -2978,8 +3046,6 @@ file_timeout(ErlDrvData e) {
enum e_timer timer_state = desc->timer_state;
#ifdef HAVE_DTRACE
dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base);
-#else
- dt_private *dt_priv = NULL;
#endif
TRACE_C('t');
@@ -2998,8 +3064,11 @@ file_timeout(ErlDrvData e) {
#ifdef DEBUG
int r =
#endif
- flush_write(desc, NULL, dt_priv,
- (desc->d == NULL) ? NULL : desc->d->sched_utag);
+ flush_write(desc, NULL
+#ifdef HAVE_DTRACE
+ , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag
+#endif
+ );
/* Only possible reason for bad return value is ENOMEM, and
* there is nobody to tell...
*/
@@ -3021,15 +3090,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
int p, q;
int err;
struct t_data *d = NULL;
+#ifdef HAVE_DTRACE
Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0;
- ERTS_DECLARE_DUMMY(Sint64 dt_i4) = 0;
+ Sint64 dt_i4 = 0;
char *dt_utag = NULL;
- ERTS_DECLARE_DUMMY(char *dt_s1) = NULL;
-#ifdef HAVE_DTRACE
+ char *dt_s1 = NULL;
dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base);
-#else
- dt_private *dt_priv = NULL;
#endif
+
TRACE_C('v');
p = 0; q = 1;
@@ -3048,9 +3116,15 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
switch (command) {
case FILE_CLOSE: {
+#ifdef HAVE_DTRACE
dt_utag = EV_CHAR_P(ev, p, q);
+#endif
flush_read(desc);
- if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
@@ -3061,9 +3135,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->command = command;
d->reply = !0;
d->fd = desc->fd;
- dt_i1 = d->fd;
d->flags = desc->flags;
+#ifdef HAVE_DTRACE
+ dt_i1 = d->fd;
dt_i2 = d->flags;
+#endif
d->invoke = invoke_close;
d->free = free_data;
d->level = 2;
@@ -3086,8 +3162,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
reply_posix_error(desc, EINVAL);
goto done;
}
+#ifdef HAVE_DTRACE
dt_utag = EV_CHAR_P(ev, p, q);
- if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) {
+#endif
+ if (flush_write_check_error(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
@@ -3095,7 +3177,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
if (desc->read_bufsize == 0 && desc->read_binp != NULL && desc->read_size > 0) {
/* We have allocated a buffer for line mode but should not really have a
read-ahead buffer... */
- if (lseek_flush_read(desc, &err, dt_priv) < 0) {
+ if (lseek_flush_read(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
@@ -3171,14 +3257,16 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->command = command;
d->reply = !0;
d->fd = desc->fd;
- dt_i1 = d->fd;
d->flags = desc->flags;
- dt_i2 = d->flags;
d->c.read.binp = desc->read_binp;
d->c.read.bin_offset = desc->read_offset + desc->read_size;
d->c.read.bin_size = desc->read_binp->orig_size - d->c.read.bin_offset;
d->c.read.size = size;
+#ifdef HAVE_DTRACE
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
dt_i3 = d->c.read.size;
+#endif
driver_binary_inc_refc(d->c.read.binp);
d->invoke = invoke_read;
d->free = free_read;
@@ -3196,12 +3284,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
* allocated binary + dealing with offsets and lengts are done in file_async ready
* for this OP.
*/
+#ifdef HAVE_DTRACE
dt_utag = EV_CHAR_P(ev, p, q);
- if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) {
+#endif
+ if (flush_write_check_error(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (ev->size != 1+strlen(dt_utag)+1) {
+ if (ev->size != 1
+#ifdef HAVE_DTRACE
+ + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE
+#endif
+ ) {
/* Wrong command length */
reply_posix_error(desc, EINVAL);
goto done;
@@ -3253,41 +3351,43 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->command = command;
d->reply = !0;
d->fd = desc->fd;
- dt_i1 = d->fd;
d->flags = desc->flags;
- dt_i2 = d->flags;
d->c.read_line.binp = desc->read_binp;
d->c.read_line.read_offset = desc->read_offset;
d->c.read_line.read_size = desc->read_size;
+#ifdef HAVE_DTRACE
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
dt_i3 = d->c.read_line.read_offset;
+#endif
#if !ALWAYS_READ_LINE_AHEAD
d->c.read_line.read_ahead = (desc->read_bufsize > 0);
-#endif
+#ifdef HAVE_DTRACE
dt_i4 = d->c.read_line.read_ahead;
+#endif
+#endif
driver_binary_inc_refc(d->c.read.binp);
d->invoke = invoke_read_line;
d->free = free_read_line;
d->level = 1;
cq_enq(desc, d);
} goto done;
- case FILE_WRITE: {
+ case FILE_WRITE: { /* Dtrace: The dtrace user tag is not last in message,
+ but follows the message tag directly.
+ This is handled specially in prim_file.erl */
ErlDrvSizeT skip = 1;
ErlDrvSizeT size = ev->size - skip;
+#ifdef HAVE_DTRACE
dt_utag = EV_CHAR_P(ev, p, q);
- skip += strlen(dt_utag) + 1;
+ skip += FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE;
size = ev->size - skip;
- /*
- * Interesting dependency on using port # for key to async
- * I/O worker pool thread: lseek_flush_read() can enqueue a
- * lseek() op. If that lseek() were scheduled on a different
- * thread than the write that we'll enqueue later in this case,
- * then Bad Things could happen. This DTrace work is probably
- * well worthwhile to get a sense of how often there's head-of-
- * line blocking/unfairness during busy file I/O because of the
- * mapping of port #/key -> thread.
- */
- if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) {
+#endif
+ if (lseek_flush_read(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
@@ -3314,8 +3414,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
driver_set_timer(desc->port, desc->write_delay);
}
} else {
- if ((d = async_write(desc, &err, !0, size,
- &dt_i1, &dt_i2, &dt_i3)) == NULL) {
+ if ((d = async_write(desc, &err, !0, size
+#ifdef HAVE_DTRACE
+ , &dt_i1, &dt_i2, &dt_i3
+#endif
+ )) == NULL) {
MUTEX_UNLOCK(desc->q_mtx);
reply_posix_error(desc, err);
goto done;
@@ -3325,27 +3428,46 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
} goto done; /* case FILE_WRITE */
- case FILE_PWRITEV: {
+ case FILE_PWRITEV: { /* Dtrace: The dtrace user tag is not last in message,
+ but follows the message tag directly.
+ This is handled specially in prim_file.erl */
Uint32 i, j, n;
size_t total;
- char tmp;
+#ifdef HAVE_DTRACE
+ char dt_tmp;
int dt_utag_bytes = 1;
dt_utag = EV_CHAR_P(ev, p, q);
- while (EV_GET_CHAR(ev, &tmp, &p, &q) && tmp != '\0') {
+ /* This will work for UTF-8, but not for UTF-16 - extra reminder here */
+#ifdef FILENAMES_16BIT
+#error 16bit characters in filenames and dtrace in combination is not supported.
+#endif
+ while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') {
dt_utag_bytes++;
}
- if (ev->size < 1+4+dt_utag_bytes
+#endif
+ if (ev->size < 1+4
+#ifdef HAVE_DTRACE
+ + dt_utag_bytes
+#endif
|| !EV_GET_UINT32(ev, &n, &p, &q)) {
/* Buffer too short to contain even the number of pos/size specs */
reply_Uint_posix_error(desc, 0, EINVAL);
goto done;
}
- if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) {
+ if (lseek_flush_read(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_Uint_posix_error(desc, 0, err);
goto done;
}
- if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_Uint_posix_error(desc, 0, err);
goto done;
}
@@ -3358,7 +3480,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
goto done;
}
- if (ev->size < 1+4+8*(2*n)+dt_utag_bytes) {
+ if (ev->size < 1+4+8*(2*n)
+#ifdef HAVE_DTRACE
+ + dt_utag_bytes
+#endif
+ ) {
/* Buffer too short to contain even the pos/size specs */
reply_Uint_posix_error(desc, 0, EINVAL);
goto done;
@@ -3372,9 +3498,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->command = command;
d->reply = !0;
d->fd = desc->fd;
- dt_i1 = d->fd;
d->flags = desc->flags;
+#ifdef HAVE_DTRACE
+ dt_i1 = d->fd;
dt_i2 = d->flags;
+#endif
d->c.pwritev.port = desc->port;
d->c.pwritev.q_mtx = desc->q_mtx;
d->c.pwritev.n = n;
@@ -3412,14 +3540,20 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
}
d->c.pwritev.size = total;
+#ifdef HAVE_DTRACE
dt_i3 = d->c.pwritev.size;
+#endif
d->c.pwritev.free_size = 0;
if (j == 0) {
/* Trivial case - nothing to write */
EF_FREE(d);
reply_Uint(desc, 0);
} else {
- ErlDrvSizeT skip = 1 + 4 + 8 * (2*n) + dt_utag_bytes;
+ ErlDrvSizeT skip = 1 + 4 + 8 * (2*n)
+#ifdef HAVE_DTRACE
+ + dt_utag_bytes
+#endif
+ ;
if (skip + total != ev->size) {
/* Actual amount of data does not match
* total of all pos/size specs
@@ -3440,33 +3574,55 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
}
} goto done; /* case FILE_PWRITEV: */
- case FILE_PREADV: {
+ case FILE_PREADV: { /* Dtrace: The dtrace user tag is not last in message,
+ but follows the message tag directly.
+ This is handled specially in prim_file.erl */
register void * void_ptr;
Uint32 i, n;
ErlIOVec *res_ev;
- char tmp;
+#ifdef HAVE_DTRACE
+ char dt_tmp;
int dt_utag_bytes = 1;
-
+ /* This will work for UTF-8, but not for UTF-16 - extra reminder here */
+#ifdef FILENAMES_16BIT
+#error 16bit characters in filenames and dtrace in combination is not supported.
+#endif
dt_utag = EV_CHAR_P(ev, p, q);
- while (EV_GET_CHAR(ev, &tmp, &p, &q) && tmp != '\0') {
+ while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') {
dt_utag_bytes++;
}
- if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) {
+#endif
+ if (lseek_flush_read(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (ev->size < 1+8+dt_utag_bytes
+ if (ev->size < 1+8
+#ifdef HAVE_DTRACE
+ + dt_utag_bytes
+#endif
|| !EV_GET_UINT32(ev, &n, &p, &q)
|| !EV_GET_UINT32(ev, &n, &p, &q)) {
/* Buffer too short to contain even the number of pos/size specs */
reply_posix_error(desc, EINVAL);
goto done;
}
- if (ev->size < 1+8+8*(2*n)+dt_utag_bytes) {
+ if (ev->size < 1+8+8*(2*n)
+#ifdef HAVE_DTRACE
+ + dt_utag_bytes
+#endif
+ ) {
/* Buffer wrong length to contain the pos/size specs */
reply_posix_error(desc, EINVAL);
goto done;
@@ -3485,9 +3641,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->command = command;
d->reply = !0;
d->fd = desc->fd;
- dt_i1 = d->fd;
d->flags = desc->flags;
+#ifdef HAVE_DTRACE
+ dt_i1 = d->fd;
dt_i2 = d->flags;
+#endif
d->c.preadv.n = n;
d->c.preadv.cnt = 0;
d->c.preadv.size = 0;
@@ -3515,7 +3673,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
#else
size = ((size_t)sizeH<<32) | sizeL;
#endif
+#ifdef HAVE_DTRACE
dt_i3 += size;
+#endif
if (! (res_ev->binv[i] = driver_alloc_binary(size))) {
reply_posix_error(desc, ENOMEM);
break;
@@ -3572,17 +3732,30 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
reply_posix_error(desc, EINVAL);
goto done;
}
+#ifdef HAVE_DTRACE
dt_utag = EV_CHAR_P(ev, p, q);
- if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) {
+#endif
+ if (lseek_flush_read(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if ((d = async_lseek(desc, &err, !0, offset, origin,
- &dt_i1, &dt_i2, &dt_i3)) == NULL) {
+ if ((d = async_lseek(desc, &err, !0, offset, origin
+#ifdef HAVE_DTRACE
+ , &dt_i1, &dt_i2, &dt_i3
+#endif
+ )) == NULL) {
reply_posix_error(desc, err);
goto done;
}
@@ -3595,11 +3768,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
reply_posix_error(desc, ENOENT);
goto done;
}
+#ifndef HAVE_DTRACE
+ /* In the dtrace case, the iov has an extra element, the dtrace utag - we will need
+ another test to see that
+ the filename is in a single buffer: */
if (ev->size-1 != ev->iov[q].iov_len-p) {
/* Name not in one single buffer */
reply_posix_error(desc, EINVAL);
goto done;
}
+#else
+ if (((byte *)ev->iov[q].iov_base)[ev->iov[q].iov_len-1] != '\0') {
+ /* Name not in one single buffer */
+ reply_posix_error(desc, EINVAL);
+ goto done;
+ }
+#endif
filename = EV_CHAR_P(ev, p, q);
d = EF_ALLOC(sizeof(struct t_data) -1 + FILENAME_BYTELEN(filename) + FILENAME_CHARSIZE);
if (! d) {
@@ -3610,8 +3794,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->reply = !0;
/* Copy name */
FILENAME_COPY(d->b, filename);
- dt_s1 = d->b;
- dt_utag = filename + strlen(d->b) + 1;
+#ifdef HAVE_DTRACE
+ {
+ char dt_tmp;
+
+ /* This will work for UTF-8, but not for UTF-16 - extra reminder here */
+#ifdef FILENAMES_16BIT
+#error 16bit characters in filenames and dtrace in combination is not supported.
+#endif
+ while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0')
+ ;
+ dt_s1 = d->b;
+ dt_utag = EV_CHAR_P(ev, p, q);
+ if (*dt_utag != 0)
+ fprintf(stderr,"dt_utag = %s\r\n",dt_utag);
+ }
+#endif
d->c.read_file.binp = NULL;
d->invoke = invoke_read_file;
d->free = free_read_file;
@@ -3650,12 +3848,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
reply_posix_error(desc, EINVAL);
goto done;
}
+#ifdef HAVE_DTRACE
dt_utag = EV_CHAR_P(ev, p, q);
- if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) {
+#endif
+ if (lseek_flush_read(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
@@ -3672,13 +3880,15 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
d->command = command;
d->reply = !0;
d->fd = desc->fd;
- dt_i1 = d->fd;
d->flags = desc->flags;
- dt_i2 = d->flags;
d->c.preadv.offsets[0] = hdr_offset;
- dt_i3 = d->c.preadv.offsets[0];
d->c.preadv.size = max_size;
+#ifdef HAVE_DTRACE
+ dt_i1 = d->fd;
+ dt_i2 = d->flags;
+ dt_i3 = d->c.preadv.offsets[0];
dt_i4 = d->c.preadv.size;
+#endif
res_ev = &d->c.preadv.eiov;
/* XXX possible alignment problems here for weird machines */
res_ev->iov = void_ptr = d + 1;
@@ -3700,12 +3910,17 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
reply_posix_error(desc, EINVAL);
goto done;
}
+#ifdef HAVE_DTRACE
dt_i1 = opt;
dt_utag = EV_CHAR_P(ev, p, q);
+#endif
switch (opt) {
case FILE_OPT_DELAYED_WRITE: {
Uint32 sizeH, sizeL, delayH, delayL;
- if (ev->size != 1+1+4*sizeof(Uint32)+strlen(dt_utag)+1
+ if (ev->size != 1+1+4*sizeof(Uint32)
+#ifdef HAVE_DTRACE
+ + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE
+#endif
|| !EV_GET_UINT32(ev, &sizeH, &p, &q)
|| !EV_GET_UINT32(ev, &sizeL, &p, &q)
|| !EV_GET_UINT32(ev, &delayH, &p, &q)
@@ -3732,13 +3947,18 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
#else
desc->write_delay = ((unsigned long)delayH << 32) | delayL;
#endif
+#ifdef HAVE_DTRACE
dt_i2 = desc->write_delay;
+#endif
TRACE_C('K');
reply_ok(desc);
} goto done;
case FILE_OPT_READ_AHEAD: {
Uint32 sizeH, sizeL;
- if (ev->size != 1+1+2*sizeof(Uint32)+strlen(dt_utag)+1
+ if (ev->size != 1+1+2*sizeof(Uint32)
+#ifdef HAVE_DTRACE
+ + FILENAME_BYTELEN(dt_utag)+FILENAME_CHARSIZE
+#endif
|| !EV_GET_UINT32(ev, &sizeH, &p, &q)
|| !EV_GET_UINT32(ev, &sizeL, &p, &q)) {
/* Buffer has wrong length to contain the option values */
@@ -3754,7 +3974,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
#else
desc->read_bufsize = ((size_t)sizeH << 32) | sizeL;
#endif
+#ifdef HAVE_DTRACE
dt_i2 = desc->read_bufsize;
+#endif
TRACE_C('K');
reply_ok(desc);
} goto done;
@@ -3841,11 +4063,19 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) {
} /* switch(command) */
- if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) {
+ if (lseek_flush_read(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
}
- if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) {
+ if (flush_write_check_error(desc, &err
+#ifdef HAVE_DTRACE
+ , dt_priv, dt_utag
+#endif
+ ) < 0) {
reply_posix_error(desc, err);
goto done;
} else {
diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam
index 6778fe353c..88c07ab4eb 100644
--- a/erts/preloaded/ebin/prim_file.beam
+++ b/erts/preloaded/ebin/prim_file.beam
Binary files differ
diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl
index 46ce3ab1a4..f7861514ae 100644
--- a/erts/preloaded/src/prim_file.erl
+++ b/erts/preloaded/src/prim_file.erl
@@ -25,59 +25,39 @@
%%% Interface towards a single file's contents. Uses ?FD_DRV.
%% Generic file contents operations
-
--export([
- open/2, open/3,
- close/1, close/2,
- datasync/1, datasync/2,
- sync/1, sync/2,
- advise/4, advise/5,
- position/2, position/3,
- truncate/1, truncate/2,
- write/2, write/3,
- pwrite/2, pwrite/3, pwrite/4,
- read/2, read/3,
- read_line/1, read_line/2,
- pread/2, pread/3, pread/4,
- copy/3, copy/4,
- sendfile/10
- ]).
+-export([open/2, close/1, datasync/1, sync/1, advise/4, position/2, truncate/1,
+ write/2, pwrite/2, pwrite/3, read/2, read_line/1, pread/2, pread/3,
+ copy/3, sendfile/10]).
%% Specialized file operations
--export([open/1]).
--export([read_file/1, read_file/2, read_file/3, write_file/2, write_file/3]).
--export([ipread_s32bu_p32bu/3, ipread_s32bu_p32bu/4]).
+-export([open/1, open/3]).
+-export([read_file/1, read_file/2, write_file/2]).
+-export([ipread_s32bu_p32bu/3]).
%%% Interface towards file system and metadata. Uses ?DRV.
%% Takes an optional port (opens a ?DRV port per default) as first argument.
-
--export([
- get_cwd/0, get_cwd/1, get_cwd/3,
- set_cwd/1, set_cwd/3,
- delete/1, delete/2, delete/3,
- rename/2, rename/3, rename/4,
- make_dir/1, make_dir/3,
- del_dir/1, del_dir/3,
- read_file_info/1, read_file_info/2, read_file_info/3, read_file_info/4,
- altname/1, altname/3,
- write_file_info/2, write_file_info/4, write_file_info/5,
- make_link/2, make_link/3, make_link/4,
- make_symlink/2, make_symlink/3, make_symlink/4,
- read_link/1, read_link/3,
- read_link_info/1, read_link_info/2, read_link_info/3, read_link_info/4,
- list_dir/1, list_dir/3
- ]).
+-export([get_cwd/0, get_cwd/1, get_cwd/2,
+ set_cwd/1, set_cwd/2,
+ delete/1, delete/2,
+ rename/2, rename/3,
+ make_dir/1, make_dir/2,
+ del_dir/1, del_dir/2,
+ read_file_info/1, read_file_info/2, read_file_info/3,
+ altname/1, altname/2,
+ write_file_info/2, write_file_info/3, write_file_info/4,
+ make_link/2, make_link/3,
+ make_symlink/2, make_symlink/3,
+ read_link/1, read_link/2,
+ read_link_info/1, read_link_info/2, read_link_info/3,
+ list_dir/1, list_dir/2]).
%% How to start and stop the ?DRV port.
-export([start/0, stop/1]).
%% Debug exports
--export([open_int/4, open_int/5, open_mode/1, open_mode/4]).
-
-%% For DTrace/Systemtap tracing
--export([get_dtrace_utag/0]).
+-export([open_int/4, open_mode/1, open_mode/4]).
%%%-----------------------------------------------------------------
%%% Includes and defines
@@ -175,21 +155,30 @@
%%% Supposed to be called by applications through module file.
-%% Opens a file. Returns {error, Reason} | {ok, FileDescriptor}.
-open(File, ModeList) ->
- open(File, ModeList, get_dtrace_utag()).
+%% Opens a file using the driver port Port. Returns {error, Reason}
+%% | {ok, FileDescriptor}
+open(Port, File, ModeList) when is_port(Port),
+ (is_list(File) orelse is_binary(File)),
+ is_list(ModeList) ->
+ case open_mode(ModeList) of
+ {Mode, _Portopts, _Setopts} ->
+ open_int(Port, File, Mode, []);
+ Reason ->
+ {error, Reason}
+ end;
+open(_,_,_) ->
+ {error, badarg}.
-open(File, ModeList, DTraceUtag)
- when (is_list(File) orelse is_binary(File)),
- is_list(ModeList),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
+%% Opens a file. Returns {error, Reason} | {ok, FileDescriptor}.
+open(File, ModeList) when (is_list(File) orelse is_binary(File)),
+ is_list(ModeList) ->
case open_mode(ModeList) of
{Mode, Portopts, Setopts} ->
- open_int({?FD_DRV, Portopts}, File, Mode, Setopts, DTraceUtag);
+ open_int({?FD_DRV, Portopts},File, Mode, Setopts);
Reason ->
{error, Reason}
end;
-open(_, _, _) ->
+open(_, _) ->
{error, badarg}.
%% Opens a port that can be used for open/3 or read_file/2.
@@ -204,34 +193,29 @@ open(Portopts) when is_list(Portopts) ->
open(_) ->
{error, badarg}.
-open_int(Arg, File, Mode, Setopts) ->
- open_int(Arg, File, Mode, Setopts, get_dtrace_utag()).
-
-open_int({Driver, Portopts}, File, Mode, Setopts, DTraceUtag) ->
- %% TODO: add DTraceUtag to drv_open()?
+open_int({Driver, Portopts}, File, Mode, Setopts) ->
case drv_open(Driver, Portopts) of
{ok, Port} ->
- open_int(Port, File, Mode, Setopts, DTraceUtag);
+ open_int(Port, File, Mode, Setopts);
{error, _} = Error ->
Error
end;
-open_int(Port, File, Mode, Setopts, DTraceUtag) ->
+open_int(Port, File, Mode, Setopts) ->
M = Mode band ?EFILE_MODE_MASK,
- case drv_command(Port, [<<?FILE_OPEN, M:32>>,
- pathname(File), enc_utag(DTraceUtag)]) of
+ case drv_command(Port, [<<?FILE_OPEN, M:32>>, pathname(File)]) of
{ok, Number} ->
- open_int_setopts(Port, Number, Setopts, DTraceUtag);
+ open_int_setopts(Port, Number, Setopts);
Error ->
drv_close(Port),
Error
end.
-open_int_setopts(Port, Number, [], _DTraceUtag) ->
+open_int_setopts(Port, Number, []) ->
{ok, #file_descriptor{module = ?MODULE, data = {Port, Number}}};
-open_int_setopts(Port, Number, [Cmd | Tail], DTraceUtag) ->
- case drv_command(Port, [Cmd, enc_utag(DTraceUtag)]) of
+open_int_setopts(Port, Number, [Cmd | Tail]) ->
+ case drv_command(Port, Cmd) of
ok ->
- open_int_setopts(Port, Number, Tail, DTraceUtag);
+ open_int_setopts(Port, Number, Tail);
Error ->
drv_close(Port),
Error
@@ -241,64 +225,50 @@ open_int_setopts(Port, Number, [Cmd | Tail], DTraceUtag) ->
%% Returns ok.
-close(Arg) ->
- close(Arg, get_dtrace_utag()).
-
-close(#file_descriptor{module = ?MODULE, data = {Port, _}}, DTraceUtag)
- when (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- case drv_command(Port, [<<?FILE_CLOSE>>, enc_utag(DTraceUtag)]) of
+close(#file_descriptor{module = ?MODULE, data = {Port, _}}) ->
+ case drv_command(Port, <<?FILE_CLOSE>>) of
ok ->
drv_close(Port);
Error ->
Error
end;
%% Closes a port opened with open/1.
-close(Port, _DTraceUtag) when is_port(Port) ->
+close(Port) when is_port(Port) ->
drv_close(Port).
--define(ADVISE(Offs, Len, Adv, BUtag),
+-define(ADVISE(Offs, Len, Adv),
<<?FILE_ADVISE, Offs:64/signed, Len:64/signed,
- Adv:32/signed, BUtag/binary>>).
+ Adv:32/signed>>).
%% Returns {error, Reason} | ok.
-advise(FD, Offset, Length, Advise) ->
- advise(FD, Offset, Length, Advise, get_dtrace_utag()).
-
advise(#file_descriptor{module = ?MODULE, data = {Port, _}},
- Offset, Length, Advise, DTraceUtag)
- when (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- BUtag = term_to_binary(enc_utag(DTraceUtag)),
+ Offset, Length, Advise) ->
case Advise of
normal ->
- Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_NORMAL, BUtag),
+ Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_NORMAL),
drv_command(Port, Cmd);
random ->
- Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_RANDOM, BUtag),
+ Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_RANDOM),
drv_command(Port, Cmd);
sequential ->
- Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_SEQUENTIAL, BUtag),
+ Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_SEQUENTIAL),
drv_command(Port, Cmd);
will_need ->
- Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_WILLNEED, BUtag),
+ Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_WILLNEED),
drv_command(Port, Cmd);
dont_need ->
- Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_DONTNEED, BUtag),
+ Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_DONTNEED),
drv_command(Port, Cmd);
no_reuse ->
- Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_NOREUSE, BUtag),
+ Cmd = ?ADVISE(Offset, Length, ?POSIX_FADV_NOREUSE),
drv_command(Port, Cmd);
_ ->
{error, einval}
end.
%% Returns {error, Reason} | ok.
-write(Desc, Bytes) ->
- write(Desc, Bytes, get_dtrace_utag()).
-
-write(#file_descriptor{module = ?MODULE, data = {Port, _}}, Bytes, DTraceUtag)
- when (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- %% This is rare case where DTraceUtag is not at end of command list.
- case drv_command(Port, [?FILE_WRITE,enc_utag(DTraceUtag),Bytes]) of
+write(#file_descriptor{module = ?MODULE, data = {Port, _}}, Bytes) ->
+ case drv_command_nt(Port, [?FILE_WRITE,erlang:prepend_vm_utag_data(Bytes)],false,undefined) of
{ok, _Size} ->
ok;
Error ->
@@ -308,40 +278,39 @@ write(#file_descriptor{module = ?MODULE, data = {Port, _}}, Bytes, DTraceUtag)
%% Returns ok | {error, {WrittenCount, Reason}}
pwrite(#file_descriptor{module = ?MODULE, data = {Port, _}}, L)
when is_list(L) ->
- pwrite_int(Port, L, 0, [], [], get_dtrace_utag()).
+ pwrite_int(Port, L, 0, [], []).
-pwrite_int(_, [], 0, [], [], _DTraceUtag) ->
+pwrite_int(_, [], 0, [], []) ->
ok;
-pwrite_int(Port, [], N, Spec, Data, DTraceUtag) ->
- Header = list_to_binary([<<?FILE_PWRITEV>>, enc_utag(DTraceUtag),
- <<N:32>>, reverse(Spec)]),
- case drv_command_raw(Port, [Header | reverse(Data)]) of
+pwrite_int(Port, [], N, Spec, Data) ->
+ Header = list_to_binary([?FILE_PWRITEV, erlang:prepend_vm_utag_data(<<N:32>>) | reverse(Spec)]),
+ case drv_command_nt(Port, [Header | reverse(Data)], false, undefined) of
{ok, _Size} ->
ok;
Error ->
Error
end;
-pwrite_int(Port, [{Offs, Bytes} | T], N, Spec, Data, DTraceUtag)
+pwrite_int(Port, [{Offs, Bytes} | T], N, Spec, Data)
when is_integer(Offs) ->
if
-(?LARGEFILESIZE) =< Offs, Offs < ?LARGEFILESIZE ->
- pwrite_int(Port, T, N, Spec, Data, Offs, Bytes, DTraceUtag);
+ pwrite_int(Port, T, N, Spec, Data, Offs, Bytes);
true ->
{error, einval}
end;
-pwrite_int(_, [_|_], _N, _Spec, _Data, _DTraceUtag) ->
+pwrite_int(_, [_|_], _N, _Spec, _Data) ->
{error, badarg}.
-pwrite_int(Port, T, N, Spec, Data, Offs, Bin, DTraceUtag)
+pwrite_int(Port, T, N, Spec, Data, Offs, Bin)
when is_binary(Bin) ->
Size = byte_size(Bin),
pwrite_int(Port, T, N+1,
[<<Offs:64/signed, Size:64>> | Spec],
- [Bin | Data], DTraceUtag);
-pwrite_int(Port, T, N, Spec, Data, Offs, Bytes, DTraceUtag) ->
+ [Bin | Data]);
+pwrite_int(Port, T, N, Spec, Data, Offs, Bytes) ->
try list_to_binary(Bytes) of
Bin ->
- pwrite_int(Port, T, N, Spec, Data, Offs, Bin, DTraceUtag)
+ pwrite_int(Port, T, N, Spec, Data, Offs, Bin)
catch
error:Reason ->
{error, Reason}
@@ -350,28 +319,11 @@ pwrite_int(Port, T, N, Spec, Data, Offs, Bytes, DTraceUtag) ->
%% Returns {error, Reason} | ok.
-pwrite(#file_descriptor{module = ?MODULE, data = {Port, _}}, L, DTraceUtag)
- when is_list(L),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- pwrite_int(Port, L, 0, [], [], DTraceUtag);
-
-pwrite(#file_descriptor{module = ?MODULE, data = {Port, _}}, Offs, Bytes)
+pwrite(#file_descriptor{module = ?MODULE, data = {Port, _}}, Offs, Bytes)
when is_integer(Offs) ->
- pwrite_int2(Port, Offs, Bytes, get_dtrace_utag());
-pwrite(#file_descriptor{module = ?MODULE}, _, _) ->
- {error, badarg}.
-
-pwrite(#file_descriptor{module = ?MODULE, data = {Port, _}}, Offs, Bytes, DTraceUtag)
- when is_integer(Offs),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- pwrite_int2(Port, Offs, Bytes, DTraceUtag);
-pwrite(#file_descriptor{module = ?MODULE}, _, _, _DTraceUtag) ->
- {error, badarg}.
-
-pwrite_int2(Port, Offs, Bytes, DTraceUtag) ->
if
-(?LARGEFILESIZE) =< Offs, Offs < ?LARGEFILESIZE ->
- case pwrite_int(Port, [], 0, [], [], Offs, Bytes, DTraceUtag) of
+ case pwrite_int(Port, [], 0, [], [], Offs, Bytes) of
{error, {_, Reason}} ->
{error, Reason};
Result ->
@@ -379,30 +331,22 @@ pwrite_int2(Port, Offs, Bytes, DTraceUtag) ->
end;
true ->
{error, einval}
- end.
-
-%% Returns {error, Reason} | ok.
-datasync(FD) ->
- datasync(FD, get_dtrace_utag()).
+ end;
+pwrite(#file_descriptor{module = ?MODULE}, _, _) ->
+ {error, badarg}.
-datasync(#file_descriptor{module = ?MODULE, data = {Port, _}}, DTraceUtag)
- when (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- drv_command(Port, [?FILE_FDATASYNC, enc_utag(DTraceUtag)]).
%% Returns {error, Reason} | ok.
-sync(FD) ->
- sync(FD, get_dtrace_utag()).
+datasync(#file_descriptor{module = ?MODULE, data = {Port, _}}) ->
+ drv_command(Port, [?FILE_FDATASYNC]).
-sync(#file_descriptor{module = ?MODULE, data = {Port, _}}, DTraceUtag)
- when (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- drv_command(Port, [?FILE_FSYNC, enc_utag(DTraceUtag)]).
+%% Returns {error, Reason} | ok.
+sync(#file_descriptor{module = ?MODULE, data = {Port, _}}) ->
+ drv_command(Port, [?FILE_FSYNC]).
%% Returns {ok, Data} | eof | {error, Reason}.
-read_line(FD) ->
- read_line(FD, get_dtrace_utag()).
-
-read_line(#file_descriptor{module = ?MODULE, data = {Port, _}}, DTraceUtag) ->
- case drv_command(Port, [<<?FILE_READ_LINE>>, enc_utag(DTraceUtag)]) of
+read_line(#file_descriptor{module = ?MODULE, data = {Port, _}}) ->
+ case drv_command(Port, <<?FILE_READ_LINE>>) of
{ok, {0, _Data}} ->
eof;
{ok, {_Size, Data}} ->
@@ -422,17 +366,11 @@ read_line(#file_descriptor{module = ?MODULE, data = {Port, _}}, DTraceUtag) ->
end.
%% Returns {ok, Data} | eof | {error, Reason}.
-read(FD, Size) ->
- read(FD, Size, get_dtrace_utag()).
-
-read(#file_descriptor{module = ?MODULE, data = {Port, _}}, Size, DTraceUtag)
- when is_integer(Size),
- 0 =< Size,
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
+read(#file_descriptor{module = ?MODULE, data = {Port, _}}, Size)
+ when is_integer(Size), 0 =< Size ->
if
Size < ?LARGEFILESIZE ->
- case drv_command(Port, [<<?FILE_READ, Size:64>>,
- enc_utag(DTraceUtag)]) of
+ case drv_command(Port, <<?FILE_READ, Size:64>>) of
{ok, {0, _Data}} when Size =/= 0 ->
eof;
{ok, {_Size, Data}} ->
@@ -441,8 +379,7 @@ read(#file_descriptor{module = ?MODULE, data = {Port, _}}, Size, DTraceUtag)
%% Garbage collecting here might help if
%% the current processes have some old binaries left.
erlang:garbage_collect(),
- case drv_command(Port, [<<?FILE_READ, Size:64>>,
- enc_utag(DTraceUtag)]) of
+ case drv_command(Port, <<?FILE_READ, Size:64>>) of
{ok, {0, _Data}} when Size =/= 0 ->
eof;
{ok, {_Size, Data}} ->
@@ -460,43 +397,35 @@ read(#file_descriptor{module = ?MODULE, data = {Port, _}}, Size, DTraceUtag)
%% Returns {ok, [Data|eof, ...]} | {error, Reason}
pread(#file_descriptor{module = ?MODULE, data = {Port, _}}, L)
when is_list(L) ->
- pread_int(Port, L, 0, [], get_dtrace_utag()).
+ pread_int(Port, L, 0, []).
-pread_int(_, [], 0, [], _DTraceUtag) ->
+pread_int(_, [], 0, []) ->
{ok, []};
-pread_int(Port, [], N, Spec, DTraceUtag) ->
- drv_command(Port, [<<?FILE_PREADV>>, enc_utag(DTraceUtag),
- <<0:32, N:32>>, reverse(Spec)]);
-pread_int(Port, [{Offs, Size} | T], N, Spec, DTraceUtag)
+pread_int(Port, [], N, Spec) ->
+ drv_command_nt(Port, [?FILE_PREADV, erlang:prepend_vm_utag_data(<<0:32, N:32>>) | reverse(Spec)],false, undefined);
+pread_int(Port, [{Offs, Size} | T], N, Spec)
when is_integer(Offs), is_integer(Size), 0 =< Size ->
if
-(?LARGEFILESIZE) =< Offs, Offs < ?LARGEFILESIZE,
Size < ?LARGEFILESIZE ->
- pread_int(Port, T, N+1, [<<Offs:64/signed, Size:64>> | Spec],
- DTraceUtag);
+ pread_int(Port, T, N+1, [<<Offs:64/signed, Size:64>> | Spec]);
true ->
{error, einval}
end;
-pread_int(_, [_|_], _N, _Spec, _DTraceUtag) ->
+pread_int(_, [_|_], _N, _Spec) ->
{error, badarg}.
+
+
%% Returns {ok, Data} | eof | {error, Reason}.
-pread(#file_descriptor{module = ?MODULE, data = {Port, _}}, L, DTraceUtag)
- when is_list(L),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- pread_int(Port, L, 0, [], get_dtrace_utag());
-pread(FD, Offs, Size)
+pread(#file_descriptor{module = ?MODULE, data = {Port, _}}, Offs, Size)
when is_integer(Offs), is_integer(Size), 0 =< Size ->
- pread(FD, Offs, Size, get_dtrace_utag()).
-
-pread(#file_descriptor{module = ?MODULE, data = {Port, _}}, Offs, Size, DTraceUtag)
- when (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
if
-(?LARGEFILESIZE) =< Offs, Offs < ?LARGEFILESIZE,
Size < ?LARGEFILESIZE ->
- case drv_command(Port,
- [<<?FILE_PREADV>>, enc_utag(DTraceUtag),
- <<0:32, 1:32, Offs:64/signed, Size:64>>]) of
+ case drv_command_nt(Port,
+ [?FILE_PREADV, erlang:prepend_vm_utag_data(<<0:32, 1:32,
+ Offs:64/signed, Size:64>>)], false, undefined) of
{ok, [eof]} ->
eof;
{ok, [Data]} ->
@@ -507,22 +436,17 @@ pread(#file_descriptor{module = ?MODULE, data = {Port, _}}, Offs, Size, DTraceUt
true ->
{error, einval}
end;
-pread(_, _, _, _) ->
+pread(#file_descriptor{module = ?MODULE, data = {_, _}}, _, _) ->
{error, badarg}.
%% Returns {ok, Position} | {error, Reason}.
-position(FD, At) ->
- position(FD, At, get_dtrace_utag()).
-
-position(#file_descriptor{module = ?MODULE, data = {Port, _}}, At, DTraceUtag)
- when (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
+position(#file_descriptor{module = ?MODULE, data = {Port, _}}, At) ->
case lseek_position(At) of
{Offs, Whence}
when -(?LARGEFILESIZE) =< Offs, Offs < ?LARGEFILESIZE ->
- drv_command(Port, [<<?FILE_LSEEK, Offs:64/signed, Whence:32>>,
- enc_utag(DTraceUtag)]);
+ drv_command(Port, <<?FILE_LSEEK, Offs:64/signed, Whence:32>>);
{_, _} ->
{error, einval};
Reason ->
@@ -530,89 +454,63 @@ position(#file_descriptor{module = ?MODULE, data = {Port, _}}, At, DTraceUtag)
end.
%% Returns {error, Reaseon} | ok.
-truncate(FD) ->
- truncate(FD, get_dtrace_utag()).
-
-truncate(#file_descriptor{module = ?MODULE, data = {Port, _}}, DTraceUtag)
- when (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- drv_command(Port, [<<?FILE_TRUNCATE>>, enc_utag(DTraceUtag)]).
+truncate(#file_descriptor{module = ?MODULE, data = {Port, _}}) ->
+ drv_command(Port, <<?FILE_TRUNCATE>>).
%% Returns {error, Reason} | {ok, BytesCopied}
-copy(Source, Dest, Length) ->
- copy(Source, Dest, Length, get_dtrace_utag()).
-
copy(#file_descriptor{module = ?MODULE} = Source,
#file_descriptor{module = ?MODULE} = Dest,
- Length, DTraceUtag)
+ Length)
when is_integer(Length), Length >= 0;
- is_atom(Length),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
+ is_atom(Length) ->
%% XXX Should be moved down to the driver for optimization.
- file:copy_opened(Source, Dest, Length, DTraceUtag).
-
+ file:copy_opened(Source, Dest, Length).
-ipread_s32bu_p32bu(FD, Offs, Arg) ->
- ipread_s32bu_p32bu(FD, Offs, Arg, get_dtrace_utag()).
ipread_s32bu_p32bu(#file_descriptor{module = ?MODULE,
data = {_, _}} = Handle,
Offs,
- Infinity,
- DTraceUtag)
- when is_atom(Infinity),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
+ Infinity) when is_atom(Infinity) ->
ipread_s32bu_p32bu(Handle, Offs, (1 bsl 31)-1);
ipread_s32bu_p32bu(#file_descriptor{module = ?MODULE, data = {Port, _}},
Offs,
- MaxSize,
- DTraceUtag)
- when is_integer(Offs),
- is_integer(MaxSize),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
+ MaxSize)
+ when is_integer(Offs), is_integer(MaxSize) ->
if
-(?LARGEFILESIZE) =< Offs, Offs < ?LARGEFILESIZE,
0 =< MaxSize, MaxSize < (1 bsl 31) ->
- drv_command(Port, [<<?FILE_IPREAD, ?IPREAD_S32BU_P32BU,
- Offs:64, MaxSize:32>>, enc_utag(DTraceUtag)]);
+ drv_command(Port, <<?FILE_IPREAD, ?IPREAD_S32BU_P32BU,
+ Offs:64, MaxSize:32>>);
true ->
{error, einval}
end;
ipread_s32bu_p32bu(#file_descriptor{module = ?MODULE, data = {_, _}},
_Offs,
- _MaxSize,
- _DTraceUtag) ->
+ _MaxSize) ->
{error, badarg}.
%% Returns {ok, Contents} | {error, Reason}
read_file(File) when (is_list(File) orelse is_binary(File)) ->
- read_file(File, get_dtrace_utag());
-read_file(_) ->
- {error, badarg}.
-
-read_file(File, DTraceUtag)
- when (is_list(File) orelse is_binary(File)),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag))->
case drv_open(?FD_DRV, [binary]) of
{ok, Port} ->
- Result = read_file(Port, File, DTraceUtag),
+ Result = read_file(Port, File),
close(Port),
Result;
{error, _} = Error ->
Error
end;
-read_file(_, _) ->
+read_file(_) ->
{error, badarg}.
%% Takes a Port opened with open/1.
-read_file(Port, File, DTraceUtag) when is_port(Port),
+read_file(Port, File) when is_port(Port),
(is_list(File) orelse is_binary(File)) ->
- Cmd = [?FILE_READ_FILE |
- list_to_binary([pathname(File), enc_utag(DTraceUtag)])],
+ Cmd = [?FILE_READ_FILE | pathname(File)],
case drv_command(Port, Cmd) of
{error, enomem} ->
%% It could possibly help to do a
@@ -624,30 +522,22 @@ read_file(Port, File, DTraceUtag) when is_port(Port),
Result ->
Result
end;
-read_file(_,_,_) ->
+read_file(_,_) ->
{error, badarg}.
%% Returns {error, Reason} | ok.
-write_file(File, Bin) ->
- write_file(File, Bin, get_dtrace_utag()).
-
-write_file(File, Bin, DTraceUtag)
- when (is_list(File) orelse is_binary(File)),
- (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) ->
- OldUtag = put(dtrace_utag, DTraceUtag), % TODO: API?
+write_file(File, Bin) when (is_list(File) orelse is_binary(File)) ->
case open(File, [binary, write]) of
{ok, Handle} ->
Result = write(Handle, Bin),
close(Handle),
- put(dtrace_utag, OldUtag),
Result;
Error ->
- put(dtrace_utag, OldUtag),
Error
end;
-write_file(_, _, _) ->
+write_file(_, _) ->
{error, badarg}.
@@ -711,56 +601,54 @@ stop(Port) when is_port(Port) ->
-%% get_cwd/{0,1,3}
+%% get_cwd/{0,1,2}
get_cwd() ->
- get_cwd_int(0, get_dtrace_utag()).
+ get_cwd_int(0).
get_cwd(Port) when is_port(Port) ->
- get_cwd_int(Port, 0, get_dtrace_utag());
+ get_cwd_int(Port, 0);
get_cwd([]) ->
- get_cwd_int(0, get_dtrace_utag());
+ get_cwd_int(0);
get_cwd([Letter, $: | _]) when $a =< Letter, Letter =< $z ->
- get_cwd_int(Letter - $a + 1, get_dtrace_utag());
+ get_cwd_int(Letter - $a + 1);
get_cwd([Letter, $: | _]) when $A =< Letter, Letter =< $Z ->
- get_cwd_int(Letter - $A + 1, get_dtrace_utag());
+ get_cwd_int(Letter - $A + 1);
get_cwd([_|_]) ->
{error, einval};
get_cwd(_) ->
{error, badarg}.
-get_cwd(Port, [], DTraceUtag) when is_port(Port) ->
- get_cwd_int(Port, 0, DTraceUtag);
-get_cwd(Port, no_drive, DTraceUtag) when is_port(Port) ->
- get_cwd_int(Port, 0, DTraceUtag);
-get_cwd(Port, [Letter, $: | _], DTraceUtag)
+get_cwd(Port, []) when is_port(Port) ->
+ get_cwd_int(Port, 0);
+get_cwd(Port, [Letter, $: | _])
when is_port(Port), $a =< Letter, Letter =< $z ->
- get_cwd_int(Port, Letter - $a + 1, DTraceUtag);
-get_cwd(Port, [Letter, $: | _], DTraceUtag)
+ get_cwd_int(Port, Letter - $a + 1);
+get_cwd(Port, [Letter, $: | _])
when is_port(Port), $A =< Letter, Letter =< $Z ->
- get_cwd_int(Port, Letter - $A + 1, DTraceUtag);
-get_cwd(Port, [_|_], _DTraceUtag) when is_port(Port) ->
+ get_cwd_int(Port, Letter - $A + 1);
+get_cwd(Port, [_|_]) when is_port(Port) ->
{error, einval};
-get_cwd(_, _, _DTraceUtag) ->
+get_cwd(_, _) ->
{error, badarg}.
-get_cwd_int(Drive, DTraceUtag) ->
- get_cwd_int({?DRV, [binary]}, Drive, DTraceUtag).
+get_cwd_int(Drive) ->
+ get_cwd_int({?DRV, [binary]}, Drive).
-get_cwd_int(Port, Drive, DTraceUtag) ->
- drv_command(Port, list_to_binary([?FILE_PWD, Drive, enc_utag(DTraceUtag)])).
+get_cwd_int(Port, Drive) ->
+ drv_command(Port, <<?FILE_PWD, Drive>>).
-%% set_cwd/{1,3}
+%% set_cwd/{1,2}
set_cwd(Dir) ->
- set_cwd_int({?DRV, [binary]}, Dir, get_dtrace_utag()).
+ set_cwd_int({?DRV, [binary]}, Dir).
-set_cwd(Port, Dir, DTraceUtag) when is_port(Port) ->
- set_cwd_int(Port, Dir, DTraceUtag).
+set_cwd(Port, Dir) when is_port(Port) ->
+ set_cwd_int(Port, Dir).
-set_cwd_int(Port, Dir0, DTraceUtag) ->
+set_cwd_int(Port, Dir0) ->
Dir =
(catch
case os:type() of
@@ -770,7 +658,7 @@ set_cwd_int(Port, Dir0, DTraceUtag) ->
%% must call get_cwd from here and use
%% absname/2, since
%% absname/1 uses file:get_cwd ...
- case get_cwd_int(Port, 0, "") of
+ case get_cwd_int(Port, 0) of
{ok, AbsPath} ->
filename:absname(Dir0, AbsPath);
_Badcwd ->
@@ -781,86 +669,78 @@ set_cwd_int(Port, Dir0, DTraceUtag) ->
end),
%% Dir is now either a string or an EXIT tuple.
%% An EXIT tuple will fail in the following catch.
- drv_command(Port, [?FILE_CHDIR, pathname(Dir), enc_utag(DTraceUtag)]).
+ drv_command(Port, [?FILE_CHDIR, pathname(Dir)]).
-%% delete/{1,2,3}
+%% delete/{1,2}
delete(File) ->
- delete_int({?DRV, [binary]}, File, get_dtrace_utag()).
+ delete_int({?DRV, [binary]}, File).
delete(Port, File) when is_port(Port) ->
- delete_int(Port, File, get_dtrace_utag()).
+ delete_int(Port, File).
-delete(Port, File, DTraceUtag) when is_port(Port) ->
- delete_int(Port, File, DTraceUtag).
+delete_int(Port, File) ->
+ drv_command(Port, [?FILE_DELETE, pathname(File)]).
-delete_int(Port, File, DTraceUtag) ->
- drv_command(Port, [?FILE_DELETE, pathname(File), enc_utag(DTraceUtag)]).
-
-%% rename/{2,3,4}
+%% rename/{2,3}
rename(From, To) ->
- rename_int({?DRV, [binary]}, From, To, get_dtrace_utag()).
+ rename_int({?DRV, [binary]}, From, To).
rename(Port, From, To) when is_port(Port) ->
- rename_int(Port, From, To, get_dtrace_utag()).
-
-rename(Port, From, To, DTraceUtag) when is_port(Port) ->
- rename_int(Port, From, To, DTraceUtag).
+ rename_int(Port, From, To).
-rename_int(Port, From, To, DTraceUtag) ->
- drv_command(Port, [?FILE_RENAME, pathname(From), pathname(To),
- enc_utag(DTraceUtag)]).
+rename_int(Port, From, To) ->
+ drv_command(Port, [?FILE_RENAME, pathname(From), pathname(To)]).
-%% make_dir/{1,3}
+%% make_dir/{1,2}
make_dir(Dir) ->
- make_dir_int({?DRV, [binary]}, Dir, get_dtrace_utag()).
+ make_dir_int({?DRV, [binary]}, Dir).
-make_dir(Port, Dir, DTraceUtag) when is_port(Port) ->
- make_dir_int(Port, Dir, DTraceUtag).
+make_dir(Port, Dir) when is_port(Port) ->
+ make_dir_int(Port, Dir).
-make_dir_int(Port, Dir, DTraceUtag) ->
- drv_command(Port, [?FILE_MKDIR, pathname(Dir), enc_utag(DTraceUtag)]).
+make_dir_int(Port, Dir) ->
+ drv_command(Port, [?FILE_MKDIR, pathname(Dir)]).
-%% del_dir/{1,3}
+%% del_dir/{1,2}
del_dir(Dir) ->
- del_dir_int({?DRV, [binary]}, Dir, get_dtrace_utag()).
+ del_dir_int({?DRV, [binary]}, Dir).
+
+del_dir(Port, Dir) when is_port(Port) ->
+ del_dir_int(Port, Dir).
-del_dir(Port, Dir, DTraceUtag) when is_port(Port) ->
- del_dir_int(Port, Dir, DTraceUtag).
+del_dir_int(Port, Dir) ->
+ drv_command(Port, [?FILE_RMDIR, pathname(Dir)]).
-del_dir_int(Port, Dir, DTraceUtag) ->
- drv_command(Port, [?FILE_RMDIR, pathname(Dir), enc_utag(DTraceUtag)]).
-%% read_file_info/{1,2,3,4}
+
+%% read_file_info/{1,2,3}
read_file_info(File) ->
- read_file_info_int({?DRV, [binary]}, File, local, get_dtrace_utag()).
+ read_file_info_int({?DRV, [binary]}, File, local).
read_file_info(Port, File) when is_port(Port) ->
- read_file_info_int(Port, File, local, get_dtrace_utag());
+ read_file_info_int(Port, File, local);
read_file_info(File, Opts) ->
- read_file_info_int({?DRV, [binary]}, File, plgv(time, Opts, local), get_dtrace_utag()).
-
-read_file_info(Port, File, Opts) when is_port(Port), is_list(Opts) ->
- read_file_info_int(Port, File, plgv(time, Opts, local), get_dtrace_utag()).
+ read_file_info_int({?DRV, [binary]}, File, plgv(time, Opts, local)).
-read_file_info(Port, File, Opts, DTraceUtag) when is_port(Port) ->
- read_file_info_int(Port, File, plgv(time, Opts, local), DTraceUtag).
+read_file_info(Port, File, Opts) when is_port(Port) ->
+ read_file_info_int(Port, File, plgv(time, Opts, local)).
-read_file_info_int(Port, File, TimeType, DTraceUtag) ->
+read_file_info_int(Port, File, TimeType) ->
try
- case drv_command(Port, [?FILE_FSTAT, pathname(File), enc_utag(DTraceUtag)]) of
+ case drv_command(Port, [?FILE_FSTAT, pathname(File)]) of
{ok, FI} -> {ok, FI#file_info{
ctime = from_seconds(FI#file_info.ctime, TimeType),
mtime = from_seconds(FI#file_info.mtime, TimeType),
@@ -872,33 +752,30 @@ read_file_info_int(Port, File, TimeType, DTraceUtag) ->
error:_ -> {error, badarg}
end.
-%% altname/{1,3}
-altname(File) ->
- altname_int({?DRV, [binary]}, File, get_dtrace_utag()).
+%% altname/{1,2}
-altname(Port, File, DTraceUtag) when is_port(Port) ->
- altname_int(Port, File, DTraceUtag).
+altname(File) ->
+ altname_int({?DRV, [binary]}, File).
-altname_int(Port, File, DTraceUtag) ->
- drv_command(Port, [?FILE_ALTNAME, pathname(File), enc_utag(DTraceUtag)]).
+altname(Port, File) when is_port(Port) ->
+ altname_int(Port, File).
+altname_int(Port, File) ->
+ drv_command(Port, [?FILE_ALTNAME, pathname(File)]).
-%% write_file_info/{2,3,4,5}
+%% write_file_info/{2,3,4}
write_file_info(File, Info) ->
- write_file_info_int({?DRV, [binary]}, File, Info, local, get_dtrace_utag()).
+ write_file_info_int({?DRV, [binary]}, File, Info, local).
write_file_info(Port, File, Info) when is_port(Port) ->
- write_file_info_int(Port, File, Info, local, get_dtrace_utag());
+ write_file_info_int(Port, File, Info, local);
write_file_info(File, Info, Opts) ->
- write_file_info_int({?DRV, [binary]}, File, Info, plgv(time, Opts, local), get_dtrace_utag()).
+ write_file_info_int({?DRV, [binary]}, File, Info, plgv(time, Opts, local)).
write_file_info(Port, File, Info, Opts) when is_port(Port) ->
- write_file_info_int(Port, File, Info, plgv(time, Opts, local), get_dtrace_utag()).
-
-write_file_info(Port, File, Info, Opts, DTraceUtag) when is_port(Port) ->
- write_file_info_int(Port, File, Info, plgv(time, Opts, local), DTraceUtag).
+ write_file_info_int(Port, File, Info, plgv(time, Opts, local)).
write_file_info_int(Port, File,
#file_info{mode=Mode,
@@ -907,8 +784,7 @@ write_file_info_int(Port, File,
atime=Atime0,
mtime=Mtime0,
ctime=Ctime0},
- TimeType,
- DTraceUtag) ->
+ TimeType) ->
% Atime and/or Mtime might be undefined
% - use localtime() for atime, if atime is undefined
@@ -927,13 +803,12 @@ write_file_info_int(Port, File,
int_to_int64bytes(to_seconds(Atime, TimeType)),
int_to_int64bytes(to_seconds(Mtime, TimeType)),
int_to_int64bytes(to_seconds(Ctime, TimeType)),
- pathname(File),
- enc_utag(DTraceUtag)
- ])
+ pathname(File)])
catch
error:_ -> {error, badarg}
end.
+
file_info_validate_atime(Atime, _) when Atime =/= undefined -> Atime;
file_info_validate_atime(undefined, local) -> erlang:localtime();
file_info_validate_atime(undefined, universal) -> erlang:universaltime();
@@ -945,72 +820,63 @@ file_info_validate_mtime(Mtime, _) -> Mtime.
file_info_validate_ctime(undefined, Mtime) -> Mtime;
file_info_validate_ctime(Ctime, _) -> Ctime.
-%% make_link/{2,3,4}
+%% make_link/{2,3}
make_link(Old, New) ->
- make_link_int({?DRV, [binary]}, Old, New, get_dtrace_utag()).
+ make_link_int({?DRV, [binary]}, Old, New).
make_link(Port, Old, New) when is_port(Port) ->
- make_link_int(Port, Old, New, get_dtrace_utag()).
+ make_link_int(Port, Old, New).
-make_link(Port, Old, New, DTraceUtag) when is_port(Port) ->
- make_link_int(Port, Old, New, DTraceUtag).
+make_link_int(Port, Old, New) ->
+ drv_command(Port, [?FILE_LINK, pathname(Old), pathname(New)]).
-make_link_int(Port, Old, New, DTraceUtag) ->
- drv_command(Port, [?FILE_LINK, pathname(Old), pathname(New),
- enc_utag(DTraceUtag)]).
-
-%% make_symlink/{2,3,4}
+%% make_symlink/{2,3}
make_symlink(Old, New) ->
- make_symlink_int({?DRV, [binary]}, Old, New, get_dtrace_utag()).
+ make_symlink_int({?DRV, [binary]}, Old, New).
make_symlink(Port, Old, New) when is_port(Port) ->
- make_symlink_int(Port, Old, New, get_dtrace_utag()).
-
-make_symlink(Port, Old, New, DTraceUtag) when is_port(Port) ->
- make_symlink_int(Port, Old, New, DTraceUtag).
+ make_symlink_int(Port, Old, New).
-make_symlink_int(Port, Old, New, DTraceUtag) ->
- drv_command(Port, [?FILE_SYMLINK, pathname(Old), pathname(New),
- enc_utag(DTraceUtag)]).
+make_symlink_int(Port, Old, New) ->
+ drv_command(Port, [?FILE_SYMLINK, pathname(Old), pathname(New)]).
-%% read_link/{1,3}
+%% read_link/{2,3}
read_link(Link) ->
- read_link_int({?DRV, [binary]}, Link, get_dtrace_utag()).
+ read_link_int({?DRV, [binary]}, Link).
-read_link(Port, Link, DTraceUtag) when is_port(Port) ->
- read_link_int(Port, Link, DTraceUtag).
+read_link(Port, Link) when is_port(Port) ->
+ read_link_int(Port, Link).
-read_link_int(Port, Link, DTraceUtag) ->
- drv_command(Port, [?FILE_READLINK, pathname(Link), enc_utag(DTraceUtag)]).
+read_link_int(Port, Link) ->
+ drv_command(Port, [?FILE_READLINK, pathname(Link)]).
-%% read_link_info/{1,2,3,4}
+%% read_link_info/{2,3}
read_link_info(Link) ->
- read_link_info_int({?DRV, [binary]}, Link, local, get_dtrace_utag()).
+ read_link_info_int({?DRV, [binary]}, Link, local).
read_link_info(Port, Link) when is_port(Port) ->
- read_link_info_int(Port, Link, local, get_dtrace_utag());
+ read_link_info_int(Port, Link, local);
+
read_link_info(Link, Opts) ->
- read_link_info_int({?DRV, [binary]}, Link, plgv(time, Opts, local), get_dtrace_utag()).
+ read_link_info_int({?DRV, [binary]}, Link, plgv(time, Opts, local)).
read_link_info(Port, Link, Opts) when is_port(Port) ->
- read_link_info_int(Port, Link, plgv(time, Opts, local), get_dtrace_utag()).
+ read_link_info_int(Port, Link, plgv(time, Opts, local)).
-read_link_info(Port, Link, Opts, DTraceUtag) when is_port(Port) ->
- read_link_info_int(Port, Link, plgv(time, Opts, local), DTraceUtag).
-read_link_info_int(Port, Link, TimeType, DTraceUtag) ->
+read_link_info_int(Port, Link, TimeType) ->
try
- case drv_command(Port, [?FILE_LSTAT, pathname(Link), enc_utag(DTraceUtag)]) of
+ case drv_command(Port, [?FILE_LSTAT, pathname(Link)]) of
{ok, FI} -> {ok, FI#file_info{
ctime = from_seconds(FI#file_info.ctime, TimeType),
mtime = from_seconds(FI#file_info.mtime, TimeType),
@@ -1022,16 +888,16 @@ read_link_info_int(Port, Link, TimeType, DTraceUtag) ->
error:_ -> {error, badarg}
end.
-%% list_dir/{1,3}
+%% list_dir/{1,2}
list_dir(Dir) ->
- list_dir_int({?DRV, [binary]}, Dir, get_dtrace_utag()).
+ list_dir_int({?DRV, [binary]}, Dir).
-list_dir(Port, Dir, DTraceUtag) when is_port(Port) ->
- list_dir_int(Port, Dir, DTraceUtag).
+list_dir(Port, Dir) when is_port(Port) ->
+ list_dir_int(Port, Dir).
-list_dir_int(Port, Dir, DTraceUtag) ->
- drv_command(Port, [?FILE_READDIR, pathname(Dir), enc_utag(DTraceUtag)], []).
+list_dir_int(Port, Dir) ->
+ drv_command(Port, [?FILE_READDIR, pathname(Dir)], []).
@@ -1057,12 +923,17 @@ drv_open(Driver, Portopts) ->
%% Closes a port in a safe way. Returns ok.
drv_close(Port) ->
- try erlang:port_close(Port) catch error:_ -> ok end,
- receive %% Ugly workaround in case the caller==owner traps exits
- {'EXIT', Port, _Reason} ->
- ok
- after 0 ->
- ok
+ Save = erlang:spread_utag(false),
+ try
+ try erlang:port_close(Port) catch error:_ -> ok end,
+ receive %% Ugly workaround in case the caller==owner traps exits
+ {'EXIT', Port, _Reason} ->
+ ok
+ after 0 ->
+ ok
+ end
+ after
+ erlang:restore_utag(Save)
end.
@@ -1072,9 +943,6 @@ drv_close(Port) ->
%% then closed after the result has been received.
%% Returns {ok, Result} or {error, Reason}.
-drv_command_raw(Port, Command) ->
- drv_command(Port, Command, false, undefined).
-
drv_command(Port, Command) ->
drv_command(Port, Command, undefined).
@@ -1090,7 +958,8 @@ drv_command(Port, Command, R) ->
end.
drv_command(Port, Command, Validated, R) when is_port(Port) ->
- try erlang:port_command(Port, Command) of
+ Save = erlang:spread_utag(false),
+ try erlang:port_command(Port, erlang:append_vm_utag_data(Command)) of
true ->
drv_get_response(Port, R)
catch
@@ -1109,6 +978,8 @@ drv_command(Port, Command, Validated, R) when is_port(Port) ->
end;
error:Reason ->
{error, Reason}
+ after
+ erlang:restore_utag(Save)
end;
drv_command({Driver, Portopts}, Command, Validated, R) ->
case drv_open(Driver, Portopts) of
@@ -1119,6 +990,30 @@ drv_command({Driver, Portopts}, Command, Validated, R) ->
Error ->
Error
end.
+drv_command_nt(Port, Command, Validated, R) when is_port(Port) ->
+ Save = erlang:spread_utag(false),
+ try erlang:port_command(Port, Command) of
+ true ->
+ drv_get_response(Port, R)
+ catch
+ %% If the Command is valid, knowing that the port is a port,
+ %% a badarg error must mean it is a dead port, that is:
+ %% a currently invalid filehandle, -> einval, not badarg.
+ error:badarg when Validated ->
+ {error, einval};
+ error:badarg ->
+ try erlang:iolist_size(Command) of
+ _ -> % Valid
+ {error, einval}
+ catch
+ error:_ ->
+ {error, badarg}
+ end;
+ error:Reason ->
+ {error, Reason}
+ after
+ erlang:restore_utag(Save)
+ end.
@@ -1469,6 +1364,7 @@ reverse(L, T) -> lists:reverse(L, T).
pathname(File) ->
(catch prim_file:internal_name2native(File)).
+
%% proplist:get_value/3
plgv(K, [{K, V}|_], _) -> V;
plgv(K, [_|KVs], D) -> plgv(K, KVs, D);
@@ -1492,16 +1388,3 @@ to_seconds({_,_} = Datetime, universal) ->
erlang:universaltime_to_posixtime(Datetime);
to_seconds({_,_} = Datetime, local) ->
erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(Datetime)).
-
-get_dtrace_utag() ->
- %% We cannot call dtrace:get_utag() because this is prim_file.erl.
- %% We must reimplement it here.
- case get('_dtrace_utag_@_@') of
- undefined ->
- <<>>;
- X ->
- X
- end.
-
-enc_utag(UTag) ->
- [UTag, 0].