Skip to content

Commit

Permalink
Merge branch 'rickard/inet_db/OTP-11074' into maint
Browse files Browse the repository at this point in the history
* rickard/inet_db/OTP-11074:
  Do not treat port_set_data/port_get_data as signals

Conflicts:
	erts/preloaded/ebin/erlang.beam
	erts/preloaded/ebin/erts_internal.beam
  • Loading branch information
rickard-green committed May 16, 2013
2 parents d7e9faf + febb796 commit 80129f4
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 309 deletions.
6 changes: 4 additions & 2 deletions erts/emulator/beam/bif.tab
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,10 @@ bif erts_internal:port_command/3
bif erts_internal:port_control/3
bif erts_internal:port_close/1
bif erts_internal:port_connect/2
bif erts_internal:port_set_data/2
bif erts_internal:port_get_data/1

# inet_db support
bif erlang:port_set_data/2
bif erlang:port_get_data/1

# Tracing & debugging.
bif erlang:trace_pattern/2
Expand Down
1 change: 1 addition & 0 deletions erts/emulator/beam/erl_alloc.types
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ type CODE_IX_LOCK_Q SHORT_LIVED SYSTEM code_ix_lock_q
type PROC_INTERVAL LONG_LIVED SYSTEM process_interval
type BUSY_CALLER_TAB SHORT_LIVED SYSTEM busy_caller_table
type BUSY_CALLER SHORT_LIVED SYSTEM busy_caller
type PORT_DATA_HEAP STANDARD SYSTEM port_data_heap

+if threads_no_smp
# Need thread safe allocs, but std_alloc and fix_alloc are not;
Expand Down
4 changes: 1 addition & 3 deletions erts/emulator/beam/erl_bif_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -2807,12 +2807,10 @@ erts_bld_port_info(Eterm **hpp, ErlOffHeap *ohp, Uint *szp, Port *prt, Eterm ite
included though).
*/
Uint size = 0;
ErlHeapFragment* bp;

erts_doforall_links(ERTS_P_LINKS(prt), &erts_one_link_size, &size);

for (bp = prt->bp; bp; bp = bp->next)
size += sizeof(ErlHeapFragment) + (bp->alloc_size - 1)*sizeof(Eterm);
size += erts_port_data_size(prt);

if (prt->linebuf)
size += sizeof(LineBuf) + prt->linebuf->ovsiz;
Expand Down
173 changes: 140 additions & 33 deletions erts/emulator/beam/erl_bif_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,57 +423,164 @@ BIF_RETTYPE erts_internal_port_info_2(BIF_ALIST_2)
}
}

/*
* The erlang:port_set_data()/erlang:port_get_data() operations should
* be viewed as operations on a table (inet_db) with data values
* associated with port identifier keys. That is, these operations are
* *not* signals to/from ports.
*/

#if (TAG_PRIMARY_IMMED1 & 0x3) == 0
# error "erlang:port_set_data()/erlang:port_get_data() needs to be rewritten!"
#endif

typedef struct {
ErtsThrPrgrLaterOp later_op;
Uint hsize;
Eterm data;
ErlOffHeap off_heap;
Eterm heap[1];
} ErtsPortDataHeap;

BIF_RETTYPE erts_internal_port_set_data_2(BIF_ALIST_2)
static void
free_port_data_heap(void *vpdhp)
{
Eterm ref;
erts_cleanup_offheap(&((ErtsPortDataHeap *) vpdhp)->off_heap);
erts_free(ERTS_ALC_T_PORT_DATA_HEAP, vpdhp);
}

static ERTS_INLINE void
cleanup_old_port_data(erts_aint_t data)
{
if ((data & 0x3) != 0) {
ASSERT(is_immed((Eterm) data));
}
else {
#ifdef ERTS_SMP
ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data;
size_t size;
ERTS_SMP_DATA_DEPENDENCY_READ_MEMORY_BARRIER;
size = sizeof(ErtsPortDataHeap) + pdhp->hsize*(sizeof(Eterm) - 1);
erts_schedule_thr_prgr_later_cleanup_op(free_port_data_heap,
(void *) pdhp,
&pdhp->later_op,
size);
#else
free_port_data_heap((void *) data);
#endif
}
}

void
erts_init_port_data(Port *prt)
{
erts_smp_atomic_init_nob(&prt->data, (erts_aint_t) am_undefined);
}

void
erts_cleanup_port_data(Port *prt)
{
ASSERT(erts_atomic32_read_nob(&prt->state) & ERTS_PORT_SFLGS_INVALID_LOOKUP);
cleanup_old_port_data(erts_smp_atomic_read_nob(&prt->data));
erts_smp_atomic_set_nob(&prt->data, (erts_aint_t) THE_NON_VALUE);
}

Uint
erts_port_data_size(Port *prt)
{
erts_aint_t data = erts_smp_atomic_read_ddrb(&prt->data);

if ((data & 0x3) != 0) {
ASSERT(is_immed((Eterm) (UWord) data));
return (Uint) 0;
}
else {
ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data;
return (Uint) sizeof(ErtsPortDataHeap) + pdhp->hsize*(sizeof(Eterm)-1);
}
}

ErlOffHeap *
erts_port_data_offheap(Port *prt)
{
erts_aint_t data = erts_smp_atomic_read_ddrb(&prt->data);

if ((data & 0x3) != 0) {
ASSERT(is_immed((Eterm) (UWord) data));
return NULL;
}
else {
ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data;
return &pdhp->off_heap;
}
}

BIF_RETTYPE port_set_data_2(BIF_ALIST_2)
{
/*
* This is not a signal. See comment above.
*/
erts_aint_t data;
Port* prt;

prt = lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
BIF_ERROR(BIF_P, BADARG);

switch (erts_port_set_data(BIF_P, prt, BIF_ARG_2, &ref)) {
case ERTS_PORT_OP_CALLER_EXIT:
case ERTS_PORT_OP_BADARG:
case ERTS_PORT_OP_DROPPED:
BIF_RET(am_badarg);
case ERTS_PORT_OP_SCHEDULED:
ASSERT(is_internal_ref(ref));
BIF_RET(ref);
case ERTS_PORT_OP_DONE:
BIF_RET(am_true);
default:
ERTS_INTERNAL_ERROR("Unexpected erts_port_set_data() result");
BIF_RET(am_internal_error);
if (is_immed(BIF_ARG_2)) {
data = (erts_aint_t) BIF_ARG_2;
ASSERT((data & 0x3) != 0);
}
else {
ErtsPortDataHeap *pdhp;
Uint hsize;
Eterm *hp;

hsize = size_object(BIF_ARG_2);
pdhp = erts_alloc(ERTS_ALC_T_PORT_DATA_HEAP,
sizeof(ErtsPortDataHeap) + hsize*(sizeof(Eterm)-1));
hp = &pdhp->heap[0];
pdhp->off_heap.first = NULL;
pdhp->off_heap.overhead = 0;
pdhp->data = copy_struct(BIF_ARG_2, hsize, &hp, &pdhp->off_heap);
data = (erts_aint_t) pdhp;
ASSERT((data & 0x3) == 0);
}

data = erts_smp_atomic_xchg_wb(&prt->data, data);

cleanup_old_port_data(data);

BIF_RET(am_true);
}


BIF_RETTYPE erts_internal_port_get_data_1(BIF_ALIST_1)
BIF_RETTYPE port_get_data_1(BIF_ALIST_1)
{
Eterm retval;
/*
* This is not a signal. See comment above.
*/
Eterm res;
erts_aint_t data;
Port* prt;

prt = lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
BIF_ERROR(BIF_P, BADARG);

switch (erts_port_get_data(BIF_P, prt, &retval)) {
case ERTS_PORT_OP_CALLER_EXIT:
case ERTS_PORT_OP_BADARG:
case ERTS_PORT_OP_DROPPED:
BIF_RET(am_badarg);
case ERTS_PORT_OP_SCHEDULED:
ASSERT(is_internal_ref(retval));
BIF_RET(retval);
case ERTS_PORT_OP_DONE:
ASSERT(is_not_internal_ref(retval));
BIF_RET(retval);
default:
ERTS_INTERNAL_ERROR("Unexpected erts_port_get_data() result");
BIF_RET(am_internal_error);
data = erts_smp_atomic_read_ddrb(&prt->data);

if ((data & 0x3) != 0) {
res = (Eterm) (UWord) data;
ASSERT(is_immed(res));
}
else {
ErtsPortDataHeap *pdhp = (ErtsPortDataHeap *) data;
Eterm *hp = HAlloc(BIF_P, pdhp->hsize);
res = copy_struct(pdhp->data, pdhp->hsize, &hp, &MSO(BIF_P));
}

BIF_RET(res);
}

/*
Expand Down
6 changes: 4 additions & 2 deletions erts/emulator/beam/erl_node_tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,7 @@ setup_reference_table(void)
/* Insert all ports */
max = erts_ptab_max(&erts_port);
for (i = 0; i < max; i++) {
ErlOffHeap *ohp;
erts_aint32_t state;
Port *prt;

Expand All @@ -1389,8 +1390,9 @@ setup_reference_table(void)
if (ERTS_P_MONITORS(prt))
insert_monitors(ERTS_P_MONITORS(prt), prt->common.id);
/* Insert port data */
for(hfp = prt->bp; hfp; hfp = hfp->next)
insert_offheap(&(hfp->off_heap), HEAP_REF, prt->common.id);
ohp = erts_port_data_offheap(prt);
if (ohp)
insert_offheap(ohp, HEAP_REF, prt->common.id);
/* Insert controller */
if (prt->dist_entry)
insert_dist_entry(prt->dist_entry,
Expand Down
19 changes: 7 additions & 12 deletions erts/emulator/beam/erl_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ struct _erl_drv_port {
#endif
erts_atomic_t connected; /* A connected process */
Eterm caller; /* Current caller. */
Eterm data; /* Data associated with port. */
ErlHeapFragment* bp; /* Heap fragment holding data (NULL if imm data). */
erts_smp_atomic_t data; /* Data associated with port. */
Uint bytes_in; /* Number of bytes read */
Uint bytes_out; /* Number of bytes written */

Expand All @@ -189,6 +188,12 @@ struct _erl_drv_port {
int reds; /* Only used while executing driver callbacks */
};


void erts_init_port_data(Port *);
void erts_cleanup_port_data(Port *);
Uint erts_port_data_size(Port *);
ErlOffHeap *erts_port_data_offheap(Port *);

#define ERTS_PORT_GET_CONNECTED(PRT) \
((Eterm) erts_atomic_read_nob(&(PRT)->connected))
#define ERTS_PORT_SET_CONNECTED(PRT, PID) \
Expand Down Expand Up @@ -326,8 +331,6 @@ extern erts_smp_atomic_t erts_bytes_in; /* no bytes sent into the system */
#define ERTS_PORT_REDS_CONTROL (CONTEXT_REDS/100)
#define ERTS_PORT_REDS_CALL (CONTEXT_REDS/50)
#define ERTS_PORT_REDS_INFO (CONTEXT_REDS/100)
#define ERTS_PORT_REDS_SET_DATA (CONTEXT_REDS/100)
#define ERTS_PORT_REDS_GET_DATA (CONTEXT_REDS/100)
#define ERTS_PORT_REDS_TERMINATE (CONTEXT_REDS/50)

void print_port_info(Port *, int, void *);
Expand Down Expand Up @@ -794,8 +797,6 @@ struct binary;
#define ERTS_P2P_SIG_TYPE_INFO 7
#define ERTS_P2P_SIG_TYPE_LINK 8
#define ERTS_P2P_SIG_TYPE_UNLINK 9
#define ERTS_P2P_SIG_TYPE_SET_DATA 10
#define ERTS_P2P_SIG_TYPE_GET_DATA 11

#define ERTS_P2P_SIG_TYPE_BITS 4
#define ERTS_P2P_SIG_TYPE_MASK \
Expand Down Expand Up @@ -856,10 +857,6 @@ struct ErtsProc2PortSigData_ {
struct {
Eterm from;
} unlink;
struct {
ErlHeapFragment *bp;
Eterm data;
} set_data;
} u;
} ;

Expand Down Expand Up @@ -953,7 +950,5 @@ ErtsPortOpResult erts_port_unlink(Process *, Port *, Eterm, Eterm *);
ErtsPortOpResult erts_port_control(Process *, Port *, unsigned int, Eterm, Eterm *);
ErtsPortOpResult erts_port_call(Process *, Port *, unsigned int, Eterm, Eterm *);
ErtsPortOpResult erts_port_info(Process *, Port *, Eterm, Eterm *);
ErtsPortOpResult erts_port_set_data(Process *, Port *, Eterm, Eterm *);
ErtsPortOpResult erts_port_get_data(Process *, Port *, Eterm *);

#endif
Loading

0 comments on commit 80129f4

Please sign in to comment.