diff options
author | Patrik Nyblom <[email protected]> | 2012-02-13 20:13:37 +0100 |
---|---|---|
committer | Patrik Nyblom <[email protected]> | 2012-03-22 18:16:14 +0100 |
commit | c15f94e7922040b63f3abf8680cd77d5548fecf3 (patch) | |
tree | 498dd289cf85393a70d4f34ff20c59338fd24066 /erts | |
parent | 0fd4e39abeea3fc87b78eec8495109f9245b5ac8 (diff) | |
download | otp-c15f94e7922040b63f3abf8680cd77d5548fecf3.tar.gz otp-c15f94e7922040b63f3abf8680cd77d5548fecf3.tar.bz2 otp-c15f94e7922040b63f3abf8680cd77d5548fecf3.zip |
Add user tag spreading functionality to VM and use in file
User tags in a dynamic trace enabled VM are spread throughout the system
in the same way as seq_trace tokens. This is used by the file module
and various other modules to get hold of the tag from the user process
without changing the protocol.
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/atom.names | 1 | ||||
-rw-r--r-- | erts/emulator/beam/beam_emu.c | 55 | ||||
-rw-r--r-- | erts/emulator/beam/bif.c | 188 | ||||
-rw-r--r-- | erts/emulator/beam/bif.tab | 17 | ||||
-rw-r--r-- | erts/emulator/beam/dist.c | 32 | ||||
-rw-r--r-- | erts/emulator/beam/erl_alloc.c | 6 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_ddll.c | 6 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_timer.c | 6 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_trace.c | 34 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_util.c | 12 | ||||
-rw-r--r-- | erts/emulator/beam/erl_gc.c | 18 | ||||
-rw-r--r-- | erts/emulator/beam/erl_message.c | 182 | ||||
-rw-r--r-- | erts/emulator/beam/erl_message.h | 13 | ||||
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 6 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 34 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 12 | ||||
-rw-r--r-- | erts/emulator/beam/erl_trace.c | 51 | ||||
-rw-r--r-- | erts/emulator/beam/io.c | 30 | ||||
-rw-r--r-- | erts/emulator/beam/utils.c | 6 | ||||
-rw-r--r-- | erts/emulator/drivers/common/efile_drv.c | 488 | ||||
-rw-r--r-- | erts/preloaded/ebin/prim_file.beam | bin | 46736 -> 38764 bytes | |||
-rw-r--r-- | erts/preloaded/src/prim_file.erl | 649 |
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 Binary files differindex 6778fe353c..88c07ab4eb 100644 --- a/erts/preloaded/ebin/prim_file.beam +++ b/erts/preloaded/ebin/prim_file.beam 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]. |