From c15f94e7922040b63f3abf8680cd77d5548fecf3 Mon Sep 17 00:00:00 2001 From: Patrik Nyblom Date: Mon, 13 Feb 2012 20:13:37 +0100 Subject: 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. --- erts/emulator/beam/atom.names | 1 + erts/emulator/beam/beam_emu.c | 55 ++- erts/emulator/beam/bif.c | 188 ++++++++- erts/emulator/beam/bif.tab | 17 + erts/emulator/beam/dist.c | 32 +- erts/emulator/beam/erl_alloc.c | 6 +- erts/emulator/beam/erl_bif_ddll.c | 6 +- erts/emulator/beam/erl_bif_timer.c | 6 +- erts/emulator/beam/erl_bif_trace.c | 34 +- erts/emulator/beam/erl_db_util.c | 12 +- erts/emulator/beam/erl_gc.c | 18 +- erts/emulator/beam/erl_message.c | 182 +++++++-- erts/emulator/beam/erl_message.h | 13 +- erts/emulator/beam/erl_nif.c | 6 +- erts/emulator/beam/erl_process.c | 34 +- erts/emulator/beam/erl_process.h | 12 + erts/emulator/beam/erl_trace.c | 51 ++- erts/emulator/beam/io.c | 30 +- erts/emulator/beam/utils.c | 6 +- erts/emulator/drivers/common/efile_drv.c | 488 +++++++++++++++++------ erts/preloaded/ebin/prim_file.beam | Bin 46736 -> 38764 bytes erts/preloaded/src/prim_file.erl | 649 +++++++++++++------------------ 22 files changed, 1254 insertions(+), 592 deletions(-) (limited to 'erts') 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 (%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 -// 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 #include @@ -149,10 +149,6 @@ typedef struct { dt_private *get_dt_private(int); #else /* HAVE_DTRACE */ -typedef struct { - char dummy; /* Unused except to quiet some compilers */ -} dt_private; - #define DTRACE_INVOKE_SETUP(op) do {} while (0) #define DTRACE_INVOKE_SETUP_BY_NAME(op) do {} while (0) #define DTRACE_INVOKE_RETURN(op) do {} while (0) @@ -212,6 +208,9 @@ typedef struct { #ifdef FILENAMES_16BIT +#ifdef HAVE_DTRACE +#error 16bit characters in filenames and dtrace in combination is not supported. +#endif # define FILENAME_BYTELEN(Str) filename_len_16bit(Str) # define FILENAME_COPY(To,From) filename_cpy_16bit((To),(From)) # define FILENAME_CHARSIZE 2 @@ -432,8 +431,6 @@ struct t_data int sched_i1; Uint64 sched_i2; char sched_utag[DTRACE_EFILE_BUFSIZ+1]; -#else - char sched_utag[1]; #endif int result_ok; Efile_error errInfo; @@ -2027,8 +2024,11 @@ static void cq_execute(file_descriptor *desc) { } static struct t_data *async_write(file_descriptor *desc, int *errp, - int reply, Uint32 reply_size, - Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3) { + int reply, Uint32 reply_size +#ifdef HAVE_DTRACE + ,Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3 +#endif +) { struct t_data *d; if (! (d = EF_ALLOC(sizeof(struct t_data) - 1))) { if (errp) *errp = ENOMEM; @@ -2041,11 +2041,13 @@ static struct t_data *async_write(file_descriptor *desc, int *errp, d->c.writev.port = desc->port; d->c.writev.q_mtx = desc->q_mtx; d->c.writev.size = desc->write_buffered; +#ifdef HAVE_DTRACE if (dt_i1 != NULL) { *dt_i1 = d->fd; *dt_i2 = d->flags; *dt_i3 = d->c.writev.size; } +#endif d->reply = reply; d->c.writev.free_size = 0; d->c.writev.reply_size = reply_size; @@ -2057,16 +2059,24 @@ static struct t_data *async_write(file_descriptor *desc, int *errp, return d; } -static int flush_write(file_descriptor *desc, int *errp, - dt_private *dt_priv, char *dt_utag) { +static int flush_write(file_descriptor *desc, int *errp +#ifdef HAVE_DTRACE + , dt_private *dt_priv, char *dt_utag +#endif +) { int result = 0; +#ifdef HAVE_DTRACE Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; +#endif struct t_data *d = NULL; MUTEX_LOCK(desc->q_mtx); if (desc->write_buffered > 0) { - if ((d = async_write(desc, errp, 0, 0, - &dt_i1, &dt_i2, &dt_i3)) == NULL) { + if ((d = async_write(desc, errp, 0, 0 +#ifdef HAVE_DTRACE + ,&dt_i1, &dt_i2, &dt_i3 +#endif + )) == NULL) { result = -1; } } @@ -2101,10 +2111,17 @@ static int check_write_error(file_descriptor *desc, int *errp) { return 0; } -static int flush_write_check_error(file_descriptor *desc, int *errp, - dt_private *dt_priv, char *dt_utag) { +static int flush_write_check_error(file_descriptor *desc, int *errp +#ifdef HAVE_DTRACE + , dt_private *dt_priv, char *dt_utag +#endif + ) { int r; - if ( (r = flush_write(desc, errp, dt_priv, dt_utag)) != 0) { + if ( (r = flush_write(desc, errp +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + )) != 0) { check_write_error(desc, NULL); return r; } else { @@ -2113,8 +2130,11 @@ static int flush_write_check_error(file_descriptor *desc, int *errp, } static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply, - Sint64 offset, int origin, - Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3) { + Sint64 offset, int origin +#ifdef HAVE_DTRACE + , Sint64 *dt_i1, Sint64 *dt_i2, Sint64 *dt_i3 +#endif + ) { struct t_data *d; if (! (d = EF_ALLOC(sizeof(struct t_data)))) { *errp = ENOMEM; @@ -2126,11 +2146,13 @@ static struct t_data *async_lseek(file_descriptor *desc, int *errp, int reply, d->reply = reply; d->c.lseek.offset = offset; d->c.lseek.origin = origin; +#ifdef HAVE_DTRACE if (dt_i1 != NULL) { *dt_i1 = d->fd; *dt_i2 = d->c.lseek.offset; *dt_i3 = d->c.lseek.origin; } +#endif d->invoke = invoke_lseek; d->free = free_data; d->level = 1; @@ -2147,18 +2169,26 @@ static void flush_read(file_descriptor *desc) { } } -static int lseek_flush_read(file_descriptor *desc, int *errp, - dt_private *dt_priv, char *dt_utag) { +static int lseek_flush_read(file_descriptor *desc, int *errp +#ifdef HAVE_DTRACE + ,dt_private *dt_priv, char *dt_utag +#endif + ) { int r = 0; size_t read_size = desc->read_size; +#ifdef HAVE_DTRACE Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; +#endif struct t_data *d; flush_read(desc); if (read_size != 0) { if ((d = async_lseek(desc, errp, 0, - -((ssize_t)read_size), EFILE_SEEK_CUR, - &dt_i1, &dt_i2, &dt_i3)) == NULL) { + -((ssize_t)read_size), EFILE_SEEK_CUR +#ifdef HAVE_DTRACE + , &dt_i1, &dt_i2, &dt_i3 +#endif + )) == NULL) { r = -1; } else { #ifdef HAVE_DTRACE @@ -2490,13 +2520,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) char* name; /* Points to the filename in buf. */ int command; struct t_data *d = NULL; - ERTS_DECLARE_DUMMY(char *dt_utag) = NULL; - char *dt_s1 = NULL, *dt_s2 = NULL; - ERTS_DECLARE_DUMMY(Sint64 dt_i1) = 0; - ERTS_DECLARE_DUMMY(Sint64 dt_i2) = 0; - ERTS_DECLARE_DUMMY(Sint64 dt_i3) = 0; - ERTS_DECLARE_DUMMY(Sint64 dt_i4) = 0; #ifdef HAVE_DTRACE + char *dt_utag = NULL; + char *dt_s1 = NULL, *dt_s2 = NULL; + Sint64 dt_i1 = 0; + Sint64 dt_i2 = 0; + Sint64 dt_i3 = 0; + Sint64 dt_i4 = 0; dt_private *dt_priv = get_dt_private(0); #endif /* HAVE_DTRACE */ @@ -2513,8 +2543,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_mkdir; d->free = free_data; @@ -2526,8 +2558,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_rmdir; d->free = free_data; @@ -2539,8 +2573,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_delete_file; d->free = free_data; @@ -2557,10 +2593,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); - dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); +#ifdef HAVE_DTRACE + dt_s1 = d->b; dt_s2 = d->b + namelen; - dt_utag = buf + namelen + strlen(dt_s2) + 1; + dt_utag = buf + namelen + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2574,8 +2612,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_chdir; d->free = free_data; @@ -2587,7 +2627,9 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); d->drive = *(uchar*)buf; +#ifdef HAVE_DTRACE dt_utag = buf + 1; +#endif d->command = command; d->invoke = invoke_pwd; d->free = free_data; @@ -2603,8 +2645,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif d->dir_handle = NULL; d->command = command; d->invoke = invoke_readdir; @@ -2629,9 +2673,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) dir_handle = NULL; resbuf[0] = FILE_RESP_LFNAME; +#ifdef HAVE_DTRACE dt_s1 = name; - dt_utag = name + strlen(dt_s1) + 1; - + dt_utag = name + FILENAME_BYTELEN(name) + FILENAME_CHARSIZE; +#endif /* Fill the buffer with multiple directory listings before sending it to the * receiving process. READDIR_CHUNKS is minimum number of files sent to the * receiver. @@ -2680,11 +2725,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); d->flags = get_int32((uchar*)buf); - dt_i1 = d->flags; name = buf+4; FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE + dt_i1 = d->flags; dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_open; d->free = free_data; @@ -2696,9 +2743,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); - dt_utag = name; d->fd = fd; +#ifdef HAVE_DTRACE + dt_utag = name; dt_i1 = fd; +#endif d->command = command; d->invoke = invoke_fdatasync; d->free = free_data; @@ -2710,9 +2759,11 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); - dt_utag = name; d->fd = fd; +#ifdef HAVE_DTRACE + dt_utag = name; dt_i1 = fd; +#endif d->command = command; d->invoke = invoke_fsync; d->free = free_data; @@ -2728,13 +2779,15 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); - dt_utag = name + strlen(d->b) + 1; d->fd = fd; +#ifdef HAVE_DTRACE + dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; if (command == FILE_LSTAT) { dt_s1 = d->b; } else { dt_i1 = fd; } +#endif d->command = command; d->invoke = invoke_flstat; d->free = free_data; @@ -2746,11 +2799,13 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data)); - dt_utag = name; d->flags = desc->flags; d->fd = fd; +#ifdef HAVE_DTRACE + dt_utag = name; dt_i1 = fd; dt_i2 = d->flags; +#endif d->command = command; d->invoke = invoke_truncate; d->free = free_data; @@ -2764,18 +2819,20 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(buf + 9*4) + FILENAME_CHARSIZE); d->info.mode = get_int32(buf + 0 * 4); - dt_i1 = d->info.mode; d->info.uid = get_int32(buf + 1 * 4); - dt_i2 = d->info.uid; d->info.gid = get_int32(buf + 2 * 4); - dt_i3 = d->info.gid; d->info.accessTime = (time_t)((Sint64)get_int64(buf + 3 * 4)); d->info.modifyTime = (time_t)((Sint64)get_int64(buf + 5 * 4)); d->info.cTime = (time_t)((Sint64)get_int64(buf + 7 * 4)); FILENAME_COPY(d->b, buf + 9*4); +#ifdef HAVE_DTRACE + dt_i1 = d->info.mode; + dt_i2 = d->info.uid; + dt_i3 = d->info.gid; dt_s1 = d->b; - dt_utag = buf + 9 * 4 + strlen(d->b) + 1; + dt_utag = buf + 9 * 4 + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_write_info; d->free = free_data; @@ -2788,8 +2845,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_readlink; d->free = free_data; @@ -2801,8 +2860,10 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) { d = EF_SAFE_ALLOC(sizeof(struct t_data) - 1 + RESBUFSIZE + 1); FILENAME_COPY(d->b, name); +#ifdef HAVE_DTRACE dt_s1 = d->b; - dt_utag = name + strlen(d->b) + 1; + dt_utag = name + FILENAME_BYTELEN(d->b) + FILENAME_CHARSIZE; +#endif d->command = command; d->invoke = invoke_altname; d->free = free_data; @@ -2822,10 +2883,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); - dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); +#ifdef HAVE_DTRACE + dt_s1 = d->b; dt_s2 = d->b + namelen; - dt_utag = buf + namelen + strlen(dt_s2) + 1; + dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE; +#endif d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2846,10 +2909,12 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) + FILENAME_BYTELEN(new_name) + FILENAME_CHARSIZE); FILENAME_COPY(d->b, name); - dt_s1 = d->b; FILENAME_COPY(d->b + namelen, new_name); +#ifdef HAVE_DTRACE + dt_s1 = d->b; dt_s2 = d->b + namelen; - dt_utag = buf + namelen + strlen(dt_s2) + 1; + dt_utag = buf + namelen + FILENAME_BYTELEN(dt_s2) + FILENAME_CHARSIZE; +#endif d->flags = desc->flags; d->fd = fd; d->command = command; @@ -2864,18 +2929,20 @@ file_output(ErlDrvData e, char* buf, ErlDrvSizeT count) d = EF_SAFE_ALLOC(sizeof(struct t_data)); d->fd = fd; - dt_i1 = d->fd; d->command = command; d->invoke = invoke_fadvise; d->free = free_data; d->level = 2; d->c.fadvise.offset = get_int64((uchar*) buf); - dt_i2 = d->c.fadvise.offset; d->c.fadvise.length = get_int64(((uchar*) buf) + sizeof(Sint64)); - dt_i3 = d->c.fadvise.length; d->c.fadvise.advise = get_int32(((uchar*) buf) + 2 * sizeof(Sint64)); +#ifdef HAVE_DTRACE + dt_i1 = d->fd; + dt_i2 = d->c.fadvise.offset; + dt_i3 = d->c.fadvise.length; dt_i4 = d->c.fadvise.advise; dt_utag = buf + 3 * sizeof(Sint64); +#endif goto done; } @@ -2920,8 +2987,6 @@ file_flush(ErlDrvData e) { #endif #ifdef HAVE_DTRACE dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); -#else - dt_private *dt_priv = NULL; #endif TRACE_C('f'); @@ -2933,8 +2998,11 @@ file_flush(ErlDrvData e) { #ifdef DEBUG r = #endif - flush_write(desc, NULL, dt_priv, - (desc->d == NULL) ? NULL : desc->d->sched_utag); + flush_write(desc, NULL +#ifdef HAVE_DTRACE + , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag +#endif + ); /* Only possible reason for bad return value is ENOMEM, and * there is nobody to tell... */ @@ -2978,8 +3046,6 @@ file_timeout(ErlDrvData e) { enum e_timer timer_state = desc->timer_state; #ifdef HAVE_DTRACE dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); -#else - dt_private *dt_priv = NULL; #endif TRACE_C('t'); @@ -2998,8 +3064,11 @@ file_timeout(ErlDrvData e) { #ifdef DEBUG int r = #endif - flush_write(desc, NULL, dt_priv, - (desc->d == NULL) ? NULL : desc->d->sched_utag); + flush_write(desc, NULL +#ifdef HAVE_DTRACE + , dt_priv, (desc->d == NULL) ? NULL : desc->d->sched_utag +#endif + ); /* Only possible reason for bad return value is ENOMEM, and * there is nobody to tell... */ @@ -3021,15 +3090,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { int p, q; int err; struct t_data *d = NULL; +#ifdef HAVE_DTRACE Sint64 dt_i1 = 0, dt_i2 = 0, dt_i3 = 0; - ERTS_DECLARE_DUMMY(Sint64 dt_i4) = 0; + Sint64 dt_i4 = 0; char *dt_utag = NULL; - ERTS_DECLARE_DUMMY(char *dt_s1) = NULL; -#ifdef HAVE_DTRACE + char *dt_s1 = NULL; dt_private *dt_priv = get_dt_private(dt_driver_io_worker_base); -#else - dt_private *dt_priv = NULL; #endif + TRACE_C('v'); p = 0; q = 1; @@ -3048,9 +3116,15 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { switch (command) { case FILE_CLOSE: { +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); +#endif flush_read(desc); - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3061,9 +3135,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; dt_i2 = d->flags; +#endif d->invoke = invoke_close; d->free = free_data; d->level = 2; @@ -3086,8 +3162,14 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3095,7 +3177,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { if (desc->read_bufsize == 0 && desc->read_binp != NULL && desc->read_size > 0) { /* We have allocated a buffer for line mode but should not really have a read-ahead buffer... */ - if (lseek_flush_read(desc, &err, dt_priv) < 0) { + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3171,14 +3257,16 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; - dt_i2 = d->flags; d->c.read.binp = desc->read_binp; d->c.read.bin_offset = desc->read_offset + desc->read_size; d->c.read.bin_size = desc->read_binp->orig_size - d->c.read.bin_offset; d->c.read.size = size; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; + dt_i2 = d->flags; dt_i3 = d->c.read.size; +#endif driver_binary_inc_refc(d->c.read.binp); d->invoke = invoke_read; d->free = free_read; @@ -3196,12 +3284,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { * allocated binary + dealing with offsets and lengts are done in file_async ready * for this OP. */ +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (ev->size != 1+strlen(dt_utag)+1) { + if (ev->size != 1 +#ifdef HAVE_DTRACE + + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE +#endif + ) { /* Wrong command length */ reply_posix_error(desc, EINVAL); goto done; @@ -3253,41 +3351,43 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; - dt_i2 = d->flags; d->c.read_line.binp = desc->read_binp; d->c.read_line.read_offset = desc->read_offset; d->c.read_line.read_size = desc->read_size; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; + dt_i2 = d->flags; dt_i3 = d->c.read_line.read_offset; +#endif #if !ALWAYS_READ_LINE_AHEAD d->c.read_line.read_ahead = (desc->read_bufsize > 0); -#endif +#ifdef HAVE_DTRACE dt_i4 = d->c.read_line.read_ahead; +#endif +#endif driver_binary_inc_refc(d->c.read.binp); d->invoke = invoke_read_line; d->free = free_read_line; d->level = 1; cq_enq(desc, d); } goto done; - case FILE_WRITE: { + case FILE_WRITE: { /* Dtrace: The dtrace user tag is not last in message, + but follows the message tag directly. + This is handled specially in prim_file.erl */ ErlDrvSizeT skip = 1; ErlDrvSizeT size = ev->size - skip; +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - skip += strlen(dt_utag) + 1; + skip += FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE; size = ev->size - skip; - /* - * Interesting dependency on using port # for key to async - * I/O worker pool thread: lseek_flush_read() can enqueue a - * lseek() op. If that lseek() were scheduled on a different - * thread than the write that we'll enqueue later in this case, - * then Bad Things could happen. This DTrace work is probably - * well worthwhile to get a sense of how often there's head-of- - * line blocking/unfairness during busy file I/O because of the - * mapping of port #/key -> thread. - */ - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3314,8 +3414,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { driver_set_timer(desc->port, desc->write_delay); } } else { - if ((d = async_write(desc, &err, !0, size, - &dt_i1, &dt_i2, &dt_i3)) == NULL) { + if ((d = async_write(desc, &err, !0, size +#ifdef HAVE_DTRACE + , &dt_i1, &dt_i2, &dt_i3 +#endif + )) == NULL) { MUTEX_UNLOCK(desc->q_mtx); reply_posix_error(desc, err); goto done; @@ -3325,27 +3428,46 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } goto done; /* case FILE_WRITE */ - case FILE_PWRITEV: { + case FILE_PWRITEV: { /* Dtrace: The dtrace user tag is not last in message, + but follows the message tag directly. + This is handled specially in prim_file.erl */ Uint32 i, j, n; size_t total; - char tmp; +#ifdef HAVE_DTRACE + char dt_tmp; int dt_utag_bytes = 1; dt_utag = EV_CHAR_P(ev, p, q); - while (EV_GET_CHAR(ev, &tmp, &p, &q) && tmp != '\0') { + /* This will work for UTF-8, but not for UTF-16 - extra reminder here */ +#ifdef FILENAMES_16BIT +#error 16bit characters in filenames and dtrace in combination is not supported. +#endif + while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') { dt_utag_bytes++; } - if (ev->size < 1+4+dt_utag_bytes +#endif + if (ev->size < 1+4 +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif || !EV_GET_UINT32(ev, &n, &p, &q)) { /* Buffer too short to contain even the number of pos/size specs */ reply_Uint_posix_error(desc, 0, EINVAL); goto done; } - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_Uint_posix_error(desc, 0, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_Uint_posix_error(desc, 0, err); goto done; } @@ -3358,7 +3480,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } goto done; } - if (ev->size < 1+4+8*(2*n)+dt_utag_bytes) { + if (ev->size < 1+4+8*(2*n) +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif + ) { /* Buffer too short to contain even the pos/size specs */ reply_Uint_posix_error(desc, 0, EINVAL); goto done; @@ -3372,9 +3498,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; dt_i2 = d->flags; +#endif d->c.pwritev.port = desc->port; d->c.pwritev.q_mtx = desc->q_mtx; d->c.pwritev.n = n; @@ -3412,14 +3540,20 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } d->c.pwritev.size = total; +#ifdef HAVE_DTRACE dt_i3 = d->c.pwritev.size; +#endif d->c.pwritev.free_size = 0; if (j == 0) { /* Trivial case - nothing to write */ EF_FREE(d); reply_Uint(desc, 0); } else { - ErlDrvSizeT skip = 1 + 4 + 8 * (2*n) + dt_utag_bytes; + ErlDrvSizeT skip = 1 + 4 + 8 * (2*n) +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif + ; if (skip + total != ev->size) { /* Actual amount of data does not match * total of all pos/size specs @@ -3440,33 +3574,55 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } } goto done; /* case FILE_PWRITEV: */ - case FILE_PREADV: { + case FILE_PREADV: { /* Dtrace: The dtrace user tag is not last in message, + but follows the message tag directly. + This is handled specially in prim_file.erl */ register void * void_ptr; Uint32 i, n; ErlIOVec *res_ev; - char tmp; +#ifdef HAVE_DTRACE + char dt_tmp; int dt_utag_bytes = 1; - + /* This will work for UTF-8, but not for UTF-16 - extra reminder here */ +#ifdef FILENAMES_16BIT +#error 16bit characters in filenames and dtrace in combination is not supported. +#endif dt_utag = EV_CHAR_P(ev, p, q); - while (EV_GET_CHAR(ev, &tmp, &p, &q) && tmp != '\0') { + while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') { dt_utag_bytes++; } - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (ev->size < 1+8+dt_utag_bytes + if (ev->size < 1+8 +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif || !EV_GET_UINT32(ev, &n, &p, &q) || !EV_GET_UINT32(ev, &n, &p, &q)) { /* Buffer too short to contain even the number of pos/size specs */ reply_posix_error(desc, EINVAL); goto done; } - if (ev->size < 1+8+8*(2*n)+dt_utag_bytes) { + if (ev->size < 1+8+8*(2*n) +#ifdef HAVE_DTRACE + + dt_utag_bytes +#endif + ) { /* Buffer wrong length to contain the pos/size specs */ reply_posix_error(desc, EINVAL); goto done; @@ -3485,9 +3641,11 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; dt_i2 = d->flags; +#endif d->c.preadv.n = n; d->c.preadv.cnt = 0; d->c.preadv.size = 0; @@ -3515,7 +3673,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else size = ((size_t)sizeH<<32) | sizeL; #endif +#ifdef HAVE_DTRACE dt_i3 += size; +#endif if (! (res_ev->binv[i] = driver_alloc_binary(size))) { reply_posix_error(desc, ENOMEM); break; @@ -3572,17 +3732,30 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if ((d = async_lseek(desc, &err, !0, offset, origin, - &dt_i1, &dt_i2, &dt_i3)) == NULL) { + if ((d = async_lseek(desc, &err, !0, offset, origin +#ifdef HAVE_DTRACE + , &dt_i1, &dt_i2, &dt_i3 +#endif + )) == NULL) { reply_posix_error(desc, err); goto done; } @@ -3595,11 +3768,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, ENOENT); goto done; } +#ifndef HAVE_DTRACE + /* In the dtrace case, the iov has an extra element, the dtrace utag - we will need + another test to see that + the filename is in a single buffer: */ if (ev->size-1 != ev->iov[q].iov_len-p) { /* Name not in one single buffer */ reply_posix_error(desc, EINVAL); goto done; } +#else + if (((byte *)ev->iov[q].iov_base)[ev->iov[q].iov_len-1] != '\0') { + /* Name not in one single buffer */ + reply_posix_error(desc, EINVAL); + goto done; + } +#endif filename = EV_CHAR_P(ev, p, q); d = EF_ALLOC(sizeof(struct t_data) -1 + FILENAME_BYTELEN(filename) + FILENAME_CHARSIZE); if (! d) { @@ -3610,8 +3794,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->reply = !0; /* Copy name */ FILENAME_COPY(d->b, filename); - dt_s1 = d->b; - dt_utag = filename + strlen(d->b) + 1; +#ifdef HAVE_DTRACE + { + char dt_tmp; + + /* This will work for UTF-8, but not for UTF-16 - extra reminder here */ +#ifdef FILENAMES_16BIT +#error 16bit characters in filenames and dtrace in combination is not supported. +#endif + while (EV_GET_CHAR(ev, &dt_tmp, &p, &q) && dt_tmp != '\0') + ; + dt_s1 = d->b; + dt_utag = EV_CHAR_P(ev, p, q); + if (*dt_utag != 0) + fprintf(stderr,"dt_utag = %s\r\n",dt_utag); + } +#endif d->c.read_file.binp = NULL; d->invoke = invoke_read_file; d->free = free_read_file; @@ -3650,12 +3848,22 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } +#ifdef HAVE_DTRACE dt_utag = EV_CHAR_P(ev, p, q); - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { +#endif + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } @@ -3672,13 +3880,15 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->command = command; d->reply = !0; d->fd = desc->fd; - dt_i1 = d->fd; d->flags = desc->flags; - dt_i2 = d->flags; d->c.preadv.offsets[0] = hdr_offset; - dt_i3 = d->c.preadv.offsets[0]; d->c.preadv.size = max_size; +#ifdef HAVE_DTRACE + dt_i1 = d->fd; + dt_i2 = d->flags; + dt_i3 = d->c.preadv.offsets[0]; dt_i4 = d->c.preadv.size; +#endif res_ev = &d->c.preadv.eiov; /* XXX possible alignment problems here for weird machines */ res_ev->iov = void_ptr = d + 1; @@ -3700,12 +3910,17 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { reply_posix_error(desc, EINVAL); goto done; } +#ifdef HAVE_DTRACE dt_i1 = opt; dt_utag = EV_CHAR_P(ev, p, q); +#endif switch (opt) { case FILE_OPT_DELAYED_WRITE: { Uint32 sizeH, sizeL, delayH, delayL; - if (ev->size != 1+1+4*sizeof(Uint32)+strlen(dt_utag)+1 + if (ev->size != 1+1+4*sizeof(Uint32) +#ifdef HAVE_DTRACE + + FILENAME_BYTELEN(dt_utag) + FILENAME_CHARSIZE +#endif || !EV_GET_UINT32(ev, &sizeH, &p, &q) || !EV_GET_UINT32(ev, &sizeL, &p, &q) || !EV_GET_UINT32(ev, &delayH, &p, &q) @@ -3732,13 +3947,18 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else desc->write_delay = ((unsigned long)delayH << 32) | delayL; #endif +#ifdef HAVE_DTRACE dt_i2 = desc->write_delay; +#endif TRACE_C('K'); reply_ok(desc); } goto done; case FILE_OPT_READ_AHEAD: { Uint32 sizeH, sizeL; - if (ev->size != 1+1+2*sizeof(Uint32)+strlen(dt_utag)+1 + if (ev->size != 1+1+2*sizeof(Uint32) +#ifdef HAVE_DTRACE + + FILENAME_BYTELEN(dt_utag)+FILENAME_CHARSIZE +#endif || !EV_GET_UINT32(ev, &sizeH, &p, &q) || !EV_GET_UINT32(ev, &sizeL, &p, &q)) { /* Buffer has wrong length to contain the option values */ @@ -3754,7 +3974,9 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { #else desc->read_bufsize = ((size_t)sizeH << 32) | sizeL; #endif +#ifdef HAVE_DTRACE dt_i2 = desc->read_bufsize; +#endif TRACE_C('K'); reply_ok(desc); } goto done; @@ -3841,11 +4063,19 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { } /* switch(command) */ - if (lseek_flush_read(desc, &err, dt_priv, dt_utag) < 0) { + if (lseek_flush_read(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } - if (flush_write_check_error(desc, &err, dt_priv, dt_utag) < 0) { + if (flush_write_check_error(desc, &err +#ifdef HAVE_DTRACE + , dt_priv, dt_utag +#endif + ) < 0) { reply_posix_error(desc, err); goto done; } else { diff --git a/erts/preloaded/ebin/prim_file.beam b/erts/preloaded/ebin/prim_file.beam index 6778fe353c..88c07ab4eb 100644 Binary files a/erts/preloaded/ebin/prim_file.beam and b/erts/preloaded/ebin/prim_file.beam differ diff --git a/erts/preloaded/src/prim_file.erl b/erts/preloaded/src/prim_file.erl index 46ce3ab1a4..f7861514ae 100644 --- a/erts/preloaded/src/prim_file.erl +++ b/erts/preloaded/src/prim_file.erl @@ -25,59 +25,39 @@ %%% Interface towards a single file's contents. Uses ?FD_DRV. %% Generic file contents operations - --export([ - open/2, open/3, - close/1, close/2, - datasync/1, datasync/2, - sync/1, sync/2, - advise/4, advise/5, - position/2, position/3, - truncate/1, truncate/2, - write/2, write/3, - pwrite/2, pwrite/3, pwrite/4, - read/2, read/3, - read_line/1, read_line/2, - pread/2, pread/3, pread/4, - copy/3, copy/4, - sendfile/10 - ]). +-export([open/2, close/1, datasync/1, sync/1, advise/4, position/2, truncate/1, + write/2, pwrite/2, pwrite/3, read/2, read_line/1, pread/2, pread/3, + copy/3, sendfile/10]). %% Specialized file operations --export([open/1]). --export([read_file/1, read_file/2, read_file/3, write_file/2, write_file/3]). --export([ipread_s32bu_p32bu/3, ipread_s32bu_p32bu/4]). +-export([open/1, open/3]). +-export([read_file/1, read_file/2, write_file/2]). +-export([ipread_s32bu_p32bu/3]). %%% Interface towards file system and metadata. Uses ?DRV. %% Takes an optional port (opens a ?DRV port per default) as first argument. - --export([ - get_cwd/0, get_cwd/1, get_cwd/3, - set_cwd/1, set_cwd/3, - delete/1, delete/2, delete/3, - rename/2, rename/3, rename/4, - make_dir/1, make_dir/3, - del_dir/1, del_dir/3, - read_file_info/1, read_file_info/2, read_file_info/3, read_file_info/4, - altname/1, altname/3, - write_file_info/2, write_file_info/4, write_file_info/5, - make_link/2, make_link/3, make_link/4, - make_symlink/2, make_symlink/3, make_symlink/4, - read_link/1, read_link/3, - read_link_info/1, read_link_info/2, read_link_info/3, read_link_info/4, - list_dir/1, list_dir/3 - ]). +-export([get_cwd/0, get_cwd/1, get_cwd/2, + set_cwd/1, set_cwd/2, + delete/1, delete/2, + rename/2, rename/3, + make_dir/1, make_dir/2, + del_dir/1, del_dir/2, + read_file_info/1, read_file_info/2, read_file_info/3, + altname/1, altname/2, + write_file_info/2, write_file_info/3, write_file_info/4, + make_link/2, make_link/3, + make_symlink/2, make_symlink/3, + read_link/1, read_link/2, + read_link_info/1, read_link_info/2, read_link_info/3, + list_dir/1, list_dir/2]). %% How to start and stop the ?DRV port. -export([start/0, stop/1]). %% Debug exports --export([open_int/4, open_int/5, open_mode/1, open_mode/4]). - -%% For DTrace/Systemtap tracing --export([get_dtrace_utag/0]). +-export([open_int/4, open_mode/1, open_mode/4]). %%%----------------------------------------------------------------- %%% Includes and defines @@ -175,21 +155,30 @@ %%% Supposed to be called by applications through module file. -%% Opens a file. Returns {error, Reason} | {ok, FileDescriptor}. -open(File, ModeList) -> - open(File, ModeList, get_dtrace_utag()). +%% Opens a file using the driver port Port. Returns {error, Reason} +%% | {ok, FileDescriptor} +open(Port, File, ModeList) when is_port(Port), + (is_list(File) orelse is_binary(File)), + is_list(ModeList) -> + case open_mode(ModeList) of + {Mode, _Portopts, _Setopts} -> + open_int(Port, File, Mode, []); + Reason -> + {error, Reason} + end; +open(_,_,_) -> + {error, badarg}. -open(File, ModeList, DTraceUtag) - when (is_list(File) orelse is_binary(File)), - is_list(ModeList), - (is_list(DTraceUtag) orelse is_binary(DTraceUtag)) -> +%% Opens a file. Returns {error, Reason} | {ok, FileDescriptor}. +open(File, ModeList) when (is_list(File) orelse is_binary(File)), + is_list(ModeList) -> case open_mode(ModeList) of {Mode, Portopts, Setopts} -> - open_int({?FD_DRV, Portopts}, File, Mode, Setopts, DTraceUtag); + open_int({?FD_DRV, Portopts},File, Mode, Setopts); Reason -> {error, Reason} end; -open(_, _, _) -> +open(_, _) -> {error, badarg}. %% Opens a port that can be used for open/3 or read_file/2. @@ -204,34 +193,29 @@ open(Portopts) when is_list(Portopts) -> open(_) -> {error, badarg}. -open_int(Arg, File, Mode, Setopts) -> - open_int(Arg, File, Mode, Setopts, get_dtrace_utag()). - -open_int({Driver, Portopts}, File, Mode, Setopts, DTraceUtag) -> - %% TODO: add DTraceUtag to drv_open()? +open_int({Driver, Portopts}, File, Mode, Setopts) -> case drv_open(Driver, Portopts) of {ok, Port} -> - open_int(Port, File, Mode, Setopts, DTraceUtag); + open_int(Port, File, Mode, Setopts); {error, _} = Error -> Error end; -open_int(Port, File, Mode, Setopts, DTraceUtag) -> +open_int(Port, File, Mode, Setopts) -> M = Mode band ?EFILE_MODE_MASK, - case drv_command(Port, [<>, - pathname(File), enc_utag(DTraceUtag)]) of + case drv_command(Port, [<>, 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, [<>, enc_utag(DTraceUtag)]) of +close(#file_descriptor{module = ?MODULE, data = {Port, _}}) -> + case drv_command(Port, <>) 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), <>). + 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([<>, enc_utag(DTraceUtag), - <>, 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(<>) | 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, [<> | 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, [<>, enc_utag(DTraceUtag)]) of +read_line(#file_descriptor{module = ?MODULE, data = {Port, _}}) -> + case drv_command(Port, <>) 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, [<>, - enc_utag(DTraceUtag)]) of + case drv_command(Port, <>) 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, [<>, - enc_utag(DTraceUtag)]) of + case drv_command(Port, <>) 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, [<>, 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, [<> | Spec], - DTraceUtag); + pread_int(Port, T, N+1, [<> | 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, - [<>, 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, [<>, - enc_utag(DTraceUtag)]); + drv_command(Port, <>); {_, _} -> {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, [<>, enc_utag(DTraceUtag)]). +truncate(#file_descriptor{module = ?MODULE, data = {Port, _}}) -> + drv_command(Port, <>). %% 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, [<>, enc_utag(DTraceUtag)]); + drv_command(Port, <>); 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, <>). -%% 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]. -- cgit v1.2.3