Example #1
0
void snippets_set_default (GuSnippets* sc) {
    GError* err = NULL;
    gchar* snip = g_build_filename (GUMMI_DATA, "snippets", "snippets.cfg", NULL);
    GList* current = sc->closure_data;

    /* Remove all accelerator */
    while (current) {
        gtk_accel_group_disconnect (sc->accel_group,
                TUPLE2 (current->data)->second);
        slog (L_DEBUG, "Accelerator for `%s' disconnected\n",
                TUPLE2 (current->data)->first);
        current = g_list_next (current);
    }
    g_list_free (sc->closure_data);
    sc->closure_data = NULL;

    if (!utils_copy_file (snip, sc->filename, &err)) {
        slog (L_G_ERROR, "can't open snippets file for writing, snippets may "
                "not work properly\n");
        g_error_free (err);
    } else {
        snippets_load (sc);
    }
    g_free (snip);
}
Example #2
0
BIF_RETTYPE
prepare_loading_2(BIF_ALIST_2)
{
    byte* temp_alloc = NULL;
    byte* code;
    Uint sz;
    Binary* magic;
    Eterm reason;
    Eterm* hp;
    Eterm res;

    if (is_not_atom(BIF_ARG_1)) {
    error:
	erts_free_aligned_binary_bytes(temp_alloc);
	BIF_ERROR(BIF_P, BADARG);
    }
    if ((code = erts_get_aligned_binary_bytes(BIF_ARG_2, &temp_alloc)) == NULL) {
	goto error;
    }

    magic = erts_alloc_loader_state();
    sz = binary_size(BIF_ARG_2);
    reason = erts_prepare_loading(magic, BIF_P, BIF_P->group_leader,
				  &BIF_ARG_1, code, sz);
    erts_free_aligned_binary_bytes(temp_alloc);
    if (reason != NIL) {
	hp = HAlloc(BIF_P, 3);
	res = TUPLE2(hp, am_error, reason);
	BIF_RET(res);
    }
    hp = HAlloc(BIF_P, PROC_BIN_SIZE);
    res = erts_mk_magic_binary_term(&hp, &MSO(BIF_P), magic);
    erts_refc_dec(&magic->refc, 1);
    BIF_RET(res);
}
Example #3
0
static void os_getenv_foreach(Process *process, Eterm *result, Eterm key, Eterm value)
{
    Eterm kvp_term, *hp;

    hp = HAlloc(process, 5);
    kvp_term = TUPLE2(hp, key, value);
    hp += 3;

    (*result) = CONS(hp, kvp_term, (*result));
}
Example #4
0
static Eterm build_load_error_hp(Eterm *hp, int code)
{
    ErrcodeEntry *ee = errcode_tab;
    while (ee->atm != NULL) {
	if (ee->code == code) {
	    return mkatom(ee->atm);
	}
	++ee;
    }
    return TUPLE2(hp,am_open_error, make_small(code));
}
Example #5
0
static void
insert_delayed_delete_node(void *state,
			   ErtsMonotonicTime timeout_pos,
			   void *vnp)
{
    DeclareTmpHeapNoproc(heap,3);
    UseTmpHeapNoproc(3);
    insert_node((ErlNode *) vnp,
		SYSTEM_REF,
		TUPLE2(&heap[0], AM_system, AM_delayed_delete_timer));
    UnUseTmpHeapNoproc(3);
}
Example #6
0
static void
insert_bif_timer(Eterm receiver, Eterm msg, ErlHeapFragment *bp, void *arg)
{
    if (bp) {
	Eterm heap[3];
	insert_offheap(&bp->off_heap,
		       TIMER_REF,
		       (is_internal_pid(receiver)
			? receiver
			: TUPLE2(&heap[0], AM_process, receiver)));
    }
}
Example #7
0
static void
insert_delayed_delete_dist_entry(void *state,
				 ErtsMonotonicTime timeout_pos,
				 void *vdep)
{
    DeclareTmpHeapNoproc(heap,3);
    UseTmpHeapNoproc(3);
    insert_dist_entry((DistEntry *) vdep,
		      SYSTEM_REF,
		      TUPLE2(&heap[0], AM_system, AM_delayed_delete_timer),
		      0);
    UnUseTmpHeapNoproc(3);
}
Example #8
0
/*
 * Build a single {M,F,A,Loction} item to be part of
 * a stack trace.
 */
Eterm*
erts_build_mfa_item(FunctionInfo* fi, Eterm* hp, Eterm args, Eterm* mfa_p)
{
    BeamInstr* current = fi->current;
    Eterm loc = NIL;

    if (fi->loc != LINE_INVALID_LOCATION) {
	Eterm tuple;
	int line = LOC_LINE(fi->loc);
	int file = LOC_FILE(fi->loc);
	Eterm file_term = NIL;

	if (file == 0) {
	    Atom* ap = atom_tab(atom_val(fi->current[0]));
	    file_term = buf_to_intlist(&hp, ".erl", 4, NIL);
	    file_term = buf_to_intlist(&hp, (char*)ap->name, ap->len, file_term);
	} else {
	    Atom* ap = atom_tab(atom_val((fi->fname_ptr)[file-1]));
	    file_term = buf_to_intlist(&hp, (char*)ap->name, ap->len, NIL);
	}

	tuple = TUPLE2(hp, am_line, make_small(line));
	hp += 3;
	loc = CONS(hp, tuple, loc);
	hp += 2;
	tuple = TUPLE2(hp, am_file, file_term);
	hp += 3;
	loc = CONS(hp, tuple, loc);
	hp += 2;
    }

    if (is_list(args) || is_nil(args)) {
	*mfa_p = TUPLE4(hp, current[0], current[1], args, loc);
    } else {
	Eterm arity = make_small(current[2]);
	*mfa_p = TUPLE4(hp, current[0], current[1], arity, loc);
    }
    return hp + 5;
}
Example #9
0
BIF_RETTYPE
lists_keysearch_3(Process* p, Eterm Key, Eterm Pos, Eterm List)
{
    Eterm res;

    res = keyfind(BIF_lists_keysearch_3, p, Key, Pos, List);
    if (is_non_value(res) || is_not_tuple(res)) {
	return res;
    } else {			/* Tuple */
	Eterm* hp = HAlloc(p, 3);
	return TUPLE2(hp, am_value, res);
    }
}
Example #10
0
BIF_RETTYPE
lists_keysearch_3(BIF_ALIST_3)
{
    Eterm res;

    res = keyfind(BIF_lists_keysearch_3, BIF_P,
		  BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
    if (is_non_value(res) || is_not_tuple(res)) {
	return res;
    } else {			/* Tuple */
	Eterm* hp = HAlloc(BIF_P, 3);
	return TUPLE2(hp, am_value, res);
    }
}
Example #11
0
static Eterm
exception_list(Process* p, Eterm tag, struct m* mp, Sint exceptions)
{
    Eterm* hp = HAlloc(p, 3 + 2*exceptions);
    Eterm res = NIL;

    while (exceptions > 0) {
	if (mp->exception) {
	    res = CONS(hp, mp->module, res);
	    hp += 2;
	    exceptions--;
	}
	mp++;
    }
    return TUPLE2(hp, tag, res);
}
Example #12
0
BIF_RETTYPE hipe_bifs_process_info_0(BIF_ALIST_0)
{
#ifdef __BENCHMARK__
#ifndef BM_COUNTERS
    Uint processes_busy	   = 0;
    Uint processes_spawned = 0;
#endif
    Eterm *hp;

    hp = HAlloc(BIF_P, 3);
    BIF_RET(TUPLE2(hp,
		   make_small(processes_busy),
		   make_small(processes_spawned)));
#else
    BIF_RET(am_false);
#endif
}
Example #13
0
File: erl_msacc.c Project: hawk/otp
/*
 * Creates a structure looking like this
 * #{ type => scheduler, id => 1, counters => #{ State1 => Counter1 ... StateN => CounterN}}
 */
static
Eterm erts_msacc_gather_stats(ErtsMsAcc *msacc, ErtsHeapFactory *factory) {
    Uint sz = 0;
    Eterm *hp, cvs[ERTS_MSACC_STATE_COUNT];
    Eterm key, state_map;
    int i;
    flatmap_t *map; 

    hp = erts_produce_heap(factory, 4, 0);
    key = TUPLE3(hp,am_counters,am_id,am_type);

    for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) {
        cvs[i] = erts_bld_sint64(NULL, &sz,(Sint64)msacc->counters[i].pc);
#ifdef ERTS_MSACC_STATE_COUNTERS
        erts_bld_uint64(NULL,&sz,msacc->counters[i].sc);
        sz += 3;
#endif
    }

    hp = erts_produce_heap(factory, sz, 0);

    for (i = 0; i < ERTS_MSACC_STATE_COUNT; i++) {
        cvs[i] = erts_bld_sint64(&hp,NULL,(Sint64)msacc->counters[i].pc);
#ifdef ERTS_MSACC_STATE_COUNTERS
        Eterm counter__ = erts_bld_uint64(&hp,NULL,msacc->counters[i].sc);
        cvs[i] = TUPLE2(hp,cvs[i],counter__);
        hp += 3;
#endif
    }

    state_map = erts_map_from_ks_and_vs(factory, erts_msacc_state_atoms, cvs,
                                        ERTS_MSACC_STATE_COUNT);

    hp = erts_produce_heap(factory, MAP_HEADER_FLATMAP_SZ + 3, 0);
    map = (flatmap_t*)hp;
    hp += MAP_HEADER_FLATMAP_SZ;
    map->thing_word = MAP_HEADER_FLATMAP;
    map->size = 3;
    map->keys = key;
    hp[0] = state_map;
    hp[1] = msacc->id;
    hp[2] = am_atom_put(msacc->type,strlen(msacc->type));

    return make_flatmap(map);
}
Example #14
0
File: sys.c Project: weisslj/otp
static void signal_notify_requested(Eterm type) {
    Process* p = NULL;
    Eterm msg, *hp;
    ErtsProcLocks locks = 0;
    ErlOffHeap *ohp;

    Eterm id = erts_whereis_name_to_id(NULL, am_erl_signal_server);

    if ((p = (erts_pid2proc_opt(NULL, 0, id, 0, ERTS_P2P_FLG_INC_REFC))) != NULL) {
        ErtsMessage *msgp = erts_alloc_message_heap(p, &locks, 3, &hp, &ohp);

        /* erl_signal_server ! {notify, sighup} */
        msg = TUPLE2(hp, am_notify, type);
        erts_queue_message(p, locks, msgp, msg, am_system);

        if (locks)
            erts_smp_proc_unlock(p, locks);
        erts_proc_dec_refc(p);
    }
}
Example #15
0
static int
dirty_send_message(Process *c_p, Eterm to, Eterm tag)
{
    ErtsProcLocks c_p_locks, rp_locks;
    Process *rp, *real_c_p;
    Eterm msg, *hp;
    ErlOffHeap *ohp;
    ErtsMessage *mp;

    ASSERT(is_immed(tag));

    real_c_p = erts_proc_shadow2real(c_p);
    if (real_c_p != c_p)
	c_p_locks = 0;
    else
	c_p_locks = ERTS_PROC_LOCK_MAIN;

    ASSERT(real_c_p->common.id == c_p->common.id);

    rp = erts_pid2proc_opt(real_c_p, c_p_locks,
			   to, 0,
			   ERTS_P2P_FLG_INC_REFC);

    if (!rp)
	return 0;

    rp_locks = 0;
    mp = erts_alloc_message_heap(rp, &rp_locks, 3, &hp, &ohp);

    msg = TUPLE2(hp, tag, c_p->common.id);
    erts_queue_message(rp, rp_locks, mp, msg, c_p->common.id);

    if (rp == real_c_p)
	rp_locks &= ~c_p_locks;
    if (rp_locks)
	erts_proc_unlock(rp, rp_locks);

    erts_proc_dec_refc(rp);

    return 1;
}
Example #16
0
void snippets_accel_disconnect (GuSnippets* sc, const gchar* key) {
    Tuple2* closure_data = NULL;
    GList* current = NULL;

    g_return_if_fail (key != NULL);

    current = sc->closure_data;
    while (current) {
        closure_data = TUPLE2 (current->data);
        if (STR_EQU (closure_data->first, key))
            break;
        current = g_list_next (current);
    }
    if (current) {
        gtk_accel_group_disconnect (sc->accel_group, closure_data->second);
        sc->closure_data = g_list_remove (sc->closure_data, closure_data);
        g_free (closure_data);
        slog (L_DEBUG, "Accelerator for `%s' disconnected\n",
                closure_data->first);
    }
}
Example #17
0
static
int ssl_tls_erl(void* arg, unsigned type, unsigned major, unsigned minor,
		const char* buf, int len, const char* prefix, int plen)
{
    struct packet_callback_args* pca = (struct packet_callback_args*) arg;
    Eterm* hp;
    Eterm ver;
    Eterm bin = new_binary(pca->p, NULL, plen+len);
    byte* bin_ptr = binary_bytes(bin);

    memcpy(bin_ptr+plen, buf, len);
    if (plen) {
        memcpy(bin_ptr, prefix, plen);
    }

    /* {ssl_tls,NIL,ContentType,{Major,Minor},Bin} */
    hp = HAlloc(pca->p, 3+6);
    ver = TUPLE2(hp, make_small(major), make_small(minor));
    hp += 3;
    pca->res = TUPLE5(hp, am_ssl_tls, NIL, make_small(type), ver, bin);
    return 1;
}
Example #18
0
/* 
 * Return list of loaded drivers {ok,[string()]} 
 */
BIF_RETTYPE erl_ddll_loaded_drivers_0(BIF_ALIST_0)
{
    Eterm *hp;
    int need = 3;
    Eterm res = NIL;
    erts_driver_t *drv;
    lock_drv_list();
    for (drv = driver_list; drv; drv = drv->next) {
	need += sys_strlen(drv->name)*2+2;
    }
    hp = HAlloc(BIF_P, need);
    for (drv = driver_list; drv; drv = drv->next) {
	Eterm l;
	l = buf_to_intlist(&hp, drv->name, sys_strlen(drv->name), NIL);
	res = CONS(hp,l,res);
	hp += 2;
    }
    res = TUPLE2(hp,am_ok,res);
    /* hp += 3 */
    unlock_drv_list();
    BIF_RET(res);
}
Example #19
0
File: erl_msacc.c Project: hawk/otp
static void send_reply(ErtsMsAcc *msacc, ErtsMSAccReq *msaccrp) {
    ErtsSchedulerData *esdp = erts_get_scheduler_data();
    Process *rp = msaccrp->proc;
    ErtsMessage *msgp = NULL;
    Eterm *hp;
    Eterm ref_copy = NIL, msg;
    ErtsProcLocks rp_locks = (esdp && msaccrp->req_sched == esdp->no
                              ? ERTS_PROC_LOCK_MAIN : 0);
    ErtsHeapFactory factory;

    if (msaccrp->action == ERTS_MSACC_GATHER) {

        msgp = erts_factory_message_create(&factory, rp, &rp_locks, DEFAULT_MSACC_MSG_SIZE);

        if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx);

        hp = erts_produce_heap(&factory, REF_THING_SIZE + 3 /* tuple */, 0);
        ref_copy = STORE_NC(&hp, &msgp->hfrag.off_heap, msaccrp->ref);
        msg = erts_msacc_gather_stats(msacc, &factory);
        msg = TUPLE2(hp, ref_copy, msg);

        if (msacc->unmanaged) erts_mtx_unlock(&msacc->mtx);

        erts_factory_close(&factory);
    } else {
        ErlOffHeap *ohp = NULL;
        msgp = erts_alloc_message_heap(rp, &rp_locks, REF_THING_SIZE, &hp, &ohp);
        msg = STORE_NC(&hp, &msgp->hfrag.off_heap, msaccrp->ref);
    }

    erts_queue_message(rp, rp_locks, msgp, msg, am_system);

    if (esdp && msaccrp->req_sched == esdp->no)
	rp_locks &= ~ERTS_PROC_LOCK_MAIN;

    if (rp_locks)
	erts_smp_proc_unlock(rp, rp_locks);

}
Example #20
0
static void notify_proc(Process *proc, Eterm ref, Eterm driver_name, Eterm type, 
			Eterm tag, int errcode)
{
    Eterm mess;
    Eterm r;
    Eterm *hp;
    ErtsMessage *mp;
    ErtsProcLocks rp_locks = 0;
    ErlOffHeap *ohp;
    ERTS_CHK_NO_PROC_LOCKS;

    assert_drv_list_rwlocked();
    if (errcode != 0) {
	int need = load_error_need(errcode);
	Eterm e;
	mp = erts_alloc_message_heap(proc, &rp_locks,
				     (6 /* tuple */ + 3 /* Error tuple */ + 
				      ERTS_REF_THING_SIZE + need),
				     &hp, &ohp);
	r = copy_ref(ref,hp);
	hp += ERTS_REF_THING_SIZE;
	e = build_load_error_hp(hp, errcode);
	hp += need;
	mess = TUPLE2(hp,tag,e);
	hp += 3;
	mess = TUPLE5(hp,type,r,am_driver,driver_name,mess);
    } else {	
	mp = erts_alloc_message_heap(proc, &rp_locks,
				     6 /* tuple */ + ERTS_REF_THING_SIZE,
				     &hp, &ohp);
	r = copy_ref(ref,hp);
	hp += ERTS_REF_THING_SIZE;
	mess = TUPLE5(hp,type,r,am_driver,driver_name,tag);
    }
    erts_queue_message(proc, rp_locks, mp, mess, am_system);
    erts_proc_unlock(proc, rp_locks);
    ERTS_CHK_NO_PROC_LOCKS;
}
Example #21
0
static int http_response_erl(void *arg, int major, int minor,
                             int status, const char* phrase, int phrase_len)
{
    /* {http_response,{Major,Minor},Status,"Phrase"} */
    struct packet_callback_args* pca = (struct packet_callback_args*) arg;    
    Eterm phrase_term, ver;
    Uint hsize = 3 + 5;
    Eterm* hp;
#ifdef DEBUG
    Eterm* hend;
#endif

    http_bld_string(pca, NULL, &hsize, phrase, phrase_len);
    hp = HAlloc(pca->p, hsize);
#ifdef DEBUG
    hend = hp + hsize;
#endif
    phrase_term = http_bld_string(pca, &hp, NULL, phrase, phrase_len);
    ver = TUPLE2(hp, make_small(major), make_small(minor));
    hp += 3;
    pca->res = TUPLE4(hp, am_http_response, ver, make_small(status), phrase_term);
    ASSERT(hp+5==hend);
    return 1;
}   
Example #22
0
/*
 decode_packet(Type,Bin,Options)
 Returns:
     {ok, PacketBodyBin, RestBin}
     {more, PacketSz | undefined}
     {error, invalid}
*/
BIF_RETTYPE decode_packet_3(BIF_ALIST_3)
{
    unsigned max_plen = 0;   /* Packet max length, 0=no limit */
    unsigned trunc_len = 0;  /* Truncate lines if longer, 0=no limit */
    int http_state = 0;      /* 0=request/response 1=header */
    int packet_sz;           /*-------Binaries involved: ------------------*/
    byte* bin_ptr;           /*| orig: original binary                     */
    byte bin_bitsz;          /*| bin: BIF_ARG_2, may be sub-binary of orig */
	                     /*| packet: prefix of bin                     */
    char* body_ptr;          /*| body: part of packet to return            */
    int body_sz;             /*| rest: bin without packet                  */
    struct packet_callback_args pca;
    enum PacketParseType type;
    Eterm* hp;
    Eterm* hend;
    ErlSubBin* rest;
    Eterm res;
    Eterm options;
    int   code;
    char  delimiter = '\n';

    if (!is_binary(BIF_ARG_2) || 
        (!is_list(BIF_ARG_3) && !is_nil(BIF_ARG_3))) {
        BIF_ERROR(BIF_P, BADARG);
    }
    switch (BIF_ARG_1) {
    case make_small(0): case am_raw: type = TCP_PB_RAW; break;
    case make_small(1): type = TCP_PB_1; break;
    case make_small(2): type = TCP_PB_2; break;
    case make_small(4): type = TCP_PB_4; break;
    case am_asn1: type = TCP_PB_ASN1; break;
    case am_sunrm: type = TCP_PB_RM; break;
    case am_cdr: type = TCP_PB_CDR; break;
    case am_fcgi: type = TCP_PB_FCGI; break;
    case am_line: type = TCP_PB_LINE_LF; break;
    case am_tpkt: type = TCP_PB_TPKT; break;
    case am_http: type = TCP_PB_HTTP; break;
    case am_httph: type = TCP_PB_HTTPH; break;
    case am_http_bin: type = TCP_PB_HTTP_BIN; break;
    case am_httph_bin: type = TCP_PB_HTTPH_BIN; break;
    case am_ssl_tls: type = TCP_PB_SSL_TLS; break;
    default:
        BIF_ERROR(BIF_P, BADARG);
    }

    options = BIF_ARG_3;
    while (!is_nil(options)) {
        Eterm* cons = list_val(options);
        if (is_tuple(CAR(cons))) {
            Eterm* tpl = tuple_val(CAR(cons));
            Uint val;
            if (tpl[0] == make_arityval(2) &&
		term_to_Uint(tpl[2],&val) && val <= UINT_MAX) {
                switch (tpl[1]) {
                case am_packet_size:
                    max_plen = val;
                    goto next_option;
                case am_line_length:
                    trunc_len = val;
                    goto next_option;
                case am_line_delimiter:
                    if (type == TCP_PB_LINE_LF && val <= 255) {
                        delimiter = (char)val;
                        goto next_option;
                    }
                }
            }
        }
        BIF_ERROR(BIF_P, BADARG);

    next_option:       
        options = CDR(cons);
    }


    pca.bin_sz = binary_size(BIF_ARG_2);
    ERTS_GET_BINARY_BYTES(BIF_ARG_2, bin_ptr, pca.bin_bitoffs, bin_bitsz);  
    if (pca.bin_bitoffs != 0) {
        pca.aligned_ptr = erts_alloc(ERTS_ALC_T_TMP, pca.bin_sz);
        erts_copy_bits(bin_ptr, pca.bin_bitoffs, 1, pca.aligned_ptr, 0, 1, pca.bin_sz*8);
    }
    else {
        pca.aligned_ptr = bin_ptr;
    }
    packet_sz = packet_get_length(type, (char*)pca.aligned_ptr, pca.bin_sz,
                                  max_plen, trunc_len, delimiter, &http_state);
    if (!(packet_sz > 0 && packet_sz <= pca.bin_sz)) {
        if (packet_sz < 0) {
	    goto error;
        }
        else { /* not enough data */
            Eterm plen = (packet_sz==0) ? am_undefined : 
                erts_make_integer(packet_sz, BIF_P);
            Eterm* hp = HAlloc(BIF_P,3);        
            res = TUPLE2(hp, am_more, plen);
            goto done;
        }
    }
    /* We got a whole packet */

    body_ptr = (char*) pca.aligned_ptr;
    body_sz = packet_sz;
    packet_get_body(type, (const char**) &body_ptr, &body_sz);

    ERTS_GET_REAL_BIN(BIF_ARG_2, pca.orig, pca.bin_offs, pca.bin_bitoffs, bin_bitsz);
    pca.p = BIF_P;
    pca.res = THE_NON_VALUE;
    pca.string_as_bin = (type == TCP_PB_HTTP_BIN || type == TCP_PB_HTTPH_BIN);
    code = packet_parse(type, (char*)pca.aligned_ptr, packet_sz, &http_state,
			&packet_callbacks_erl, &pca);
    if (code == 0) { /* no special packet parsing, make plain binary */
        ErlSubBin* body;
        Uint hsz = 2*ERL_SUB_BIN_SIZE + 4;
        hp = HAlloc(BIF_P, hsz);
        hend = hp + hsz;

        body = (ErlSubBin *) hp;
        body->thing_word = HEADER_SUB_BIN;
        body->size = body_sz;
        body->offs = pca.bin_offs + (body_ptr - (char*)pca.aligned_ptr);
        body->orig = pca.orig;
        body->bitoffs = pca.bin_bitoffs;
        body->bitsize = 0;
        body->is_writable = 0;
        hp += ERL_SUB_BIN_SIZE;
        pca.res = make_binary(body);
    }
    else if (code > 0) {
	Uint hsz = ERL_SUB_BIN_SIZE + 4;
	ASSERT(pca.res != THE_NON_VALUE);
	hp = HAlloc(BIF_P, hsz);
	hend = hp + hsz;
    }
    else {
error:
	hp = HAlloc(BIF_P,3);        
	res = TUPLE2(hp, am_error, am_invalid);
	goto done;
    }

    rest = (ErlSubBin *) hp;
    rest->thing_word = HEADER_SUB_BIN;
    rest->size = pca.bin_sz - packet_sz;
    rest->offs = pca.bin_offs + packet_sz;
    rest->orig = pca.orig;
    rest->bitoffs = pca.bin_bitoffs;
    rest->bitsize = bin_bitsz;   /* The extra bits go into the rest. */
    rest->is_writable = 0;
    hp += ERL_SUB_BIN_SIZE;
    res = TUPLE3(hp, am_ok, pca.res, make_binary(rest));
    hp += 4;
    ASSERT(hp==hend); (void)hend;

done:
    if (pca.aligned_ptr != bin_ptr) {
        erts_free(ERTS_ALC_T_TMP, pca.aligned_ptr);
    }
    BIF_RET(res);
}
Example #23
0
static Eterm pd_hash_put(Process *p, Eterm id, Eterm value)
{ 
    unsigned int hval;
    Eterm *hp;
    Eterm tpl;
    Eterm old;
    Eterm tmp;
    int needed;
    int i = 0;
#ifdef DEBUG
    Eterm *hp_limit;
#endif

    if (p->dictionary == NULL) {
	/* Create it */
	array_put(&(p->dictionary), INITIAL_SIZE - 1, NIL);
	p->dictionary->homeSize = INITIAL_SIZE;
    }	
    hval = pd_hash_value(p->dictionary, id);
    old = ARRAY_GET(p->dictionary, hval);

    /*
     * Calculate the number of heap words needed and garbage
     * collect if necessary. (Might be a slight overestimation.)
     */
    needed = 3;			/* {Key,Value} tuple */
    if (is_boxed(old)) {
	/*
	 * We don't want to compare keys twice, so we'll always
	 * reserve the space for two CONS cells.
	 */
	needed += 2+2;
    } else if (is_list(old)) {
	i = 0;
	for (tmp = old; tmp != NIL && !EQ(tuple_val(TCAR(tmp))[1], id); tmp = TCDR(tmp)) {
	    ++i;
	}
	if (is_nil(tmp)) {
	    i = -1;
	    needed += 2;
	} else {
	    needed += 2*(i+1);
	}
    }
    if (HeapWordsLeft(p) < needed) {
	Eterm root[3];
	root[0] = id;
	root[1] = value;
	root[2] = old;
	BUMP_REDS(p, erts_garbage_collect(p, needed, root, 3));
	id = root[0];
	value = root[1];
	old = root[2];
    }
#ifdef DEBUG
    hp_limit = p->htop + needed;
#endif

    /*
     * Create the {Key,Value} tuple.
     */
    hp = HeapOnlyAlloc(p, 3);
    tpl = TUPLE2(hp, id, value);

    /*
     * Update the dictionary.
     */
    if (is_nil(old)) {
	array_put(&(p->dictionary), hval, tpl);
	++(p->dictionary->numElements);
    } else if (is_boxed(old)) {
	ASSERT(is_tuple(old));
	if (EQ(tuple_val(old)[1],id)) {
	    array_put(&(p->dictionary), hval, tpl);
	    return tuple_val(old)[2];
	} else {
	    hp = HeapOnlyAlloc(p, 4);
	    tmp = CONS(hp, old, NIL);
	    hp += 2;
	    ++(p->dictionary->numElements);
	    array_put(&(p->dictionary), hval, CONS(hp, tpl, tmp));
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	}
    } else if (is_list(old)) {
	if (i == -1) {
	    /*
	     * New key. Simply prepend the tuple to the beginning of the list.
	     */
	    hp = HeapOnlyAlloc(p, 2);
	    array_put(&(p->dictionary), hval, CONS(hp, tpl, old));
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	    ++(p->dictionary->numElements);
	} else {
	    /*
	     * i = Number of CDRs to skip to reach the changed element in the list.
	     *
	     * Replace old value in list. To avoid pointers from the old generation
	     * to the new, we must rebuild the list from the beginning up to and
	     * including the changed element.
	     */
	    Eterm nlist;
	    int j;

	    hp = HeapOnlyAlloc(p, (i+1)*2);
	    
	    /* Find the list element to change. */
	    for (j = 0, nlist = old; j < i; j++, nlist = TCDR(nlist)) {
		;
	    }
	    ASSERT(EQ(tuple_val(TCAR(nlist))[1], id));
	    nlist = TCDR(nlist); /* Unchanged part of list. */

	    /* Rebuild list before the updated element. */
	    for (tmp = old; i-- > 0; tmp = TCDR(tmp)) {
		nlist = CONS(hp, TCAR(tmp), nlist);
		hp += 2;
	    }
	    ASSERT(EQ(tuple_val(TCAR(tmp))[1], id));

	    /* Put the updated element first in the new list. */
	    nlist = CONS(hp, tpl, nlist);
	    hp += 2;
	    ASSERT(hp <= hp_limit);
	    array_put(&(p->dictionary), hval, nlist);
	    return tuple_val(TCAR(tmp))[2];
	}
    } else {
#ifdef DEBUG
	erts_fprintf(stderr,
		     "Process dictionary for process %T is broken, trying to "
		     "display term found in line %d:\n"
		     "%T\n", p->common.id, __LINE__, old);
#endif

	erl_exit(1, "Damaged process dictionary found during put/2.");
    }
    if (HASH_RANGE(p->dictionary) <= p->dictionary->numElements) {
	grow(p);
    }
    return am_undefined;
}
Example #24
0
Eterm erts_instr_get_memory_map(Process *proc)
{
    MapStatBlock_t *org_mem_anchor;
    Eterm hdr_tuple, md_list, res;
    Eterm *hp;
    Uint hsz;
    MapStatBlock_t *bp;
#ifdef DEBUG
    Eterm *end_hp;
#endif
    
    if (!erts_instr_memory_map)
	return am_false;

    if (!atoms_initialized)
	init_atoms();
    if (!am_n)
	init_am_n();
    if (!am_c)
	init_am_c();
    if (!am_a)
	init_am_a();

    erts_mtx_lock(&instr_x_mutex);
    erts_mtx_lock(&instr_mutex);

    /* Header size */
    hsz = 5 + 1 + (ERTS_ALC_N_MAX+1-ERTS_ALC_N_MIN)*(1 + 4);

    /* Memory data list */
    for (bp = mem_anchor; bp; bp = bp->next) {
	if (is_internal_pid(bp->pid)) {
#if (_PID_NUM_SIZE - 1 > MAX_SMALL)
	    if (internal_pid_number(bp->pid) > MAX_SMALL)
		hsz += BIG_UINT_HEAP_SIZE;
#endif
#if (_PID_SER_SIZE - 1 > MAX_SMALL)
	    if (internal_pid_serial(bp->pid) > MAX_SMALL)
		hsz += BIG_UINT_HEAP_SIZE;
#endif
	    hsz += 4;
	}

	if ((UWord) bp->mem > MAX_SMALL)
	    hsz += BIG_UINT_HEAP_SIZE;
	if (bp->size > MAX_SMALL)
	    hsz += BIG_UINT_HEAP_SIZE;

	hsz += 5 + 2;
    }

    hsz += 3; /* Root tuple */

    org_mem_anchor = mem_anchor;
    mem_anchor = NULL;

    erts_mtx_unlock(&instr_mutex);

    hp = HAlloc(proc, hsz); /* May end up calling map_stat_alloc() */

    erts_mtx_lock(&instr_mutex);

#ifdef DEBUG
    end_hp = hp + hsz;
#endif

    {	/* Build header */
	ErtsAlcType_t n;
	Eterm type_map;
	Uint *hp2 = hp;
#ifdef DEBUG
	Uint *hp2_end;
#endif

	hp += (ERTS_ALC_N_MAX + 1 - ERTS_ALC_N_MIN)*4;

#ifdef DEBUG
	hp2_end = hp;
#endif

	type_map = make_tuple(hp);
	*(hp++) = make_arityval(ERTS_ALC_N_MAX + 1 - ERTS_ALC_N_MIN);

	for (n = ERTS_ALC_N_MIN; n <= ERTS_ALC_N_MAX; n++) {
	    ErtsAlcType_t t = ERTS_ALC_N2T(n);
	    ErtsAlcType_t a = ERTS_ALC_T2A(t);
	    ErtsAlcType_t c = ERTS_ALC_T2C(t);

	    if (!erts_allctrs_info[a].enabled)
		a = ERTS_ALC_A_SYSTEM;

	    *(hp++) = TUPLE3(hp2, am_n[n], am_a[a], am_c[c]);
	    hp2 += 4;
	}

	ASSERT(hp2 == hp2_end);

	hdr_tuple = TUPLE4(hp,
			   am.instr_hdr,
			   make_small(ERTS_INSTR_VSN),
			   make_small(MAP_STAT_BLOCK_HEADER_SIZE),
			   type_map);

	hp += 5;
    }

    /* Build memory data list */

    for (md_list = NIL, bp = org_mem_anchor; bp; bp = bp->next) {
	Eterm tuple;
	Eterm type;
	Eterm ptr;
	Eterm size;
	Eterm pid;

	if (is_not_internal_pid(bp->pid))
	    pid = am_undefined;
	else {
	    Eterm c;
	    Eterm n;
	    Eterm s;

#if (ERST_INTERNAL_CHANNEL_NO > MAX_SMALL)
#error Oversized internal channel number
#endif
	    c = make_small(ERST_INTERNAL_CHANNEL_NO);

#if (_PID_NUM_SIZE - 1 > MAX_SMALL)
	    if (internal_pid_number(bp->pid) > MAX_SMALL) {
		n = uint_to_big(internal_pid_number(bp->pid), hp);
		hp += BIG_UINT_HEAP_SIZE;
	    }
	    else
#endif
		n = make_small(internal_pid_number(bp->pid));

#if (_PID_SER_SIZE - 1 > MAX_SMALL)
	    if (internal_pid_serial(bp->pid) > MAX_SMALL) {
		s = uint_to_big(internal_pid_serial(bp->pid), hp);
		hp += BIG_UINT_HEAP_SIZE;
	    }
	    else
#endif
		s = make_small(internal_pid_serial(bp->pid));
	    pid = TUPLE3(hp, c, n, s);
	    hp += 4;
	}


#if ERTS_ALC_N_MAX > MAX_SMALL
#error Oversized memory type number
#endif
	type = make_small(bp->type_no);

	if ((UWord) bp->mem > MAX_SMALL) {
	    ptr = uint_to_big((UWord) bp->mem, hp);
	    hp += BIG_UINT_HEAP_SIZE;
	}
	else
	    ptr = make_small((UWord) bp->mem);

	if (bp->size > MAX_SMALL) {
	    size = uint_to_big(bp->size, hp);
	    hp += BIG_UINT_HEAP_SIZE;
	}
	else
	    size = make_small(bp->size);

	tuple = TUPLE4(hp, type, ptr, size, pid);
	hp += 5;

	md_list = CONS(hp, tuple, md_list);
	hp += 2;
    }

    res = TUPLE2(hp, hdr_tuple, md_list);
    
    ASSERT(hp + 3 == end_hp);

    if (mem_anchor) {
	for (bp = mem_anchor; bp->next; bp = bp->next)
	    ;
	ASSERT(org_mem_anchor);
	org_mem_anchor->prev = bp; 
	bp->next = org_mem_anchor;
    }
    else {
	mem_anchor = org_mem_anchor;
    }

    erts_mtx_unlock(&instr_mutex);
    erts_mtx_unlock(&instr_x_mutex);

    return res;
}
Example #25
0
/* 
 * More detailed info about loaded drivers: 
 * item is processes, driver_options, port_count, linked_in_driver, 
 * permanent, awaiting_load, awaiting_unload 
 */
BIF_RETTYPE erl_ddll_info_2(BIF_ALIST_2)
{
    Process *p = BIF_P;
    Eterm name_term = BIF_ARG_1;
    Eterm item = BIF_ARG_2;
    char *name = NULL;
    Eterm res = NIL;
    erts_driver_t *drv;
    ProcEntryInfo *pei = NULL;
    int num_pei;
    Eterm *hp;
    int i;
    Uint filter;
    int have_lock = 0;

    if ((name = pick_list_or_atom(name_term)) == NULL) {
	goto error;
    }

    if (!is_atom(item)) {
	goto error;
    }

    lock_drv_list();
    have_lock = 1;
    if ((drv = lookup_driver(name)) == NULL) {
	goto error;
    }
    
    switch (item) {
    case am_processes:
	filter = ERL_DE_PROC_LOADED;
	break;
    case am_driver_options:
	if (drv->handle == NULL) {
	    res = am_linked_in_driver;
	} else {
	    Uint start_flags = drv->handle->flags & ERL_FL_CONSISTENT_MASK;
	    /* Cheating, only one flag for now... */
	    if (start_flags & ERL_DE_FL_KILL_PORTS) {
		Eterm *myhp;
		myhp = HAlloc(p,2);
		res = CONS(myhp,am_kill_ports,NIL);
	    } else {
		res = NIL;
	    }
	}
	goto done;
    case am_port_count:
	if (drv->handle == NULL) {
	    res = am_linked_in_driver;
	} else if (drv->handle->status == ERL_DE_PERMANENT) {
	    res = am_permanent;
	} else {
	    res = make_small(erts_atomic32_read_nob(&drv->handle->port_count));
	}
	goto done;
    case am_linked_in_driver:
	if (drv->handle == NULL){
	    res = am_true;
	} else {
	    res = am_false;
	}
	goto done;
    case am_permanent:
	if (drv->handle != NULL && drv->handle->status == ERL_DE_PERMANENT) {
	    res = am_true;
	} else {
	    res = am_false;
	}
	goto done;
    case am_awaiting_load:
	filter = ERL_DE_PROC_AWAIT_LOAD;
	break;
    case am_awaiting_unload:
	filter = ERL_DE_PROC_AWAIT_UNLOAD;
	break;
    default:
	goto error;
    }

    if (drv->handle == NULL) {
	res = am_linked_in_driver;
	goto done;
    } else if (drv->handle->status == ERL_DE_PERMANENT) {
	res = am_permanent;
	goto done;
    }
    num_pei = build_proc_info(drv->handle, &pei, filter);
    if (!num_pei) {
	goto done;
    }
    hp = HAlloc(p,num_pei * (2+3));
    for (i = 0; i < num_pei; ++ i) {
	Eterm tpl = TUPLE2(hp,pei[i].pid,make_small(pei[i].count));
	hp += 3;
	res = CONS(hp,tpl,res);
	hp += 2;
    }    
 done:    
    unlock_drv_list();
    if (pei)
	erts_free(ERTS_ALC_T_DDLL_TMP_BUF, pei);
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    BIF_RET(res);
 error:
    if (name != NULL) {
	erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    }
    if (have_lock) {
	unlock_drv_list();
    }
    BIF_ERROR(p,BADARG);
}
Example #26
0
static BIF_RETTYPE
dirty_test(Process *c_p, Eterm type, Eterm arg1, Eterm arg2, UWord *I)
{
    BIF_RETTYPE ret;
    if (am_scheduler == arg1) {
	ErtsSchedulerData *esdp;
	if (arg2 != am_type) 
	    goto badarg;
	esdp = erts_proc_sched_data(c_p);
	if (!esdp)
            goto scheduler_type_error;
      
        switch (esdp->type) {
        case ERTS_SCHED_NORMAL:
	    ERTS_BIF_PREP_RET(ret, am_normal);
            break;
        case ERTS_SCHED_DIRTY_CPU:
	    ERTS_BIF_PREP_RET(ret, am_dirty_cpu);
            break;
        case ERTS_SCHED_DIRTY_IO:
	    ERTS_BIF_PREP_RET(ret, am_dirty_io);
            break;
        default:
        scheduler_type_error:
	    ERTS_BIF_PREP_RET(ret, am_error);
            break;
        }
    }
    else if (am_error == arg1) {
	switch (arg2) {
	case am_notsup:
	    ERTS_BIF_PREP_ERROR(ret, c_p, EXC_NOTSUP);
	    break;
	case am_undef:
	    ERTS_BIF_PREP_ERROR(ret, c_p, EXC_UNDEF);
	    break;
	case am_badarith:
	    ERTS_BIF_PREP_ERROR(ret, c_p, EXC_BADARITH);
	    break;
	case am_noproc:
	    ERTS_BIF_PREP_ERROR(ret, c_p, EXC_NOPROC);
	    break;
	case am_system_limit:
	    ERTS_BIF_PREP_ERROR(ret, c_p, SYSTEM_LIMIT);
	    break;
	case am_badarg:
	default:
	    goto badarg;
	}
    }
    else if (am_copy == arg1) {
	int i;
	Eterm res;

	for (res = NIL, i = 0; i < 1000; i++) {
	    Eterm *hp, sz;
	    Eterm cpy;
	    /* We do not want this to be optimized,
	       but rather the oposite... */
	    sz = size_object(arg2);
	    hp = HAlloc(c_p, sz);
	    cpy = copy_struct(arg2, sz, &hp, &c_p->off_heap);
	    hp = HAlloc(c_p, 2);
	    res = CONS(hp, cpy, res);
	}

	ERTS_BIF_PREP_RET(ret, res);
    }
    else if (am_send == arg1) {
	dirty_send_message(c_p, arg2, am_ok);
	ERTS_BIF_PREP_RET(ret, am_ok);
    }
    else if (ERTS_IS_ATOM_STR("wait", arg1)) {
	if (!ms_wait(c_p, arg2, type == am_dirty_cpu))
	    goto badarg;
	ERTS_BIF_PREP_RET(ret, am_ok);
    }
    else if (ERTS_IS_ATOM_STR("reschedule", arg1)) {
	/*
	 * Reschedule operation after decrement of two until we reach
	 * zero. Switch between dirty scheduler types when 'n' is
	 * evenly divided by 4. If the initial value wasn't evenly
	 * dividable by 2, throw badarg exception.
	 */
	Eterm next_type;
	Sint n;
	if (!term_to_Sint(arg2, &n) || n < 0)
	    goto badarg;
	if (n == 0)
	    ERTS_BIF_PREP_RET(ret, am_ok);
	else {
	    Eterm argv[3];
	    Eterm eint = erts_make_integer((Uint) (n - 2), c_p);
	    if (n % 4 != 0)
		next_type = type;
	    else {
		switch (type) {
		case am_dirty_cpu: next_type = am_dirty_io; break;
		case am_dirty_io: next_type = am_normal; break;
		case am_normal: next_type = am_dirty_cpu; break;
		default: goto badarg;
		}
	    }
	    switch (next_type) {
	    case am_dirty_io:
		argv[0] = arg1;
		argv[1] = eint;
		ret = erts_schedule_bif(c_p,
					argv,
					I,
					erts_debug_dirty_io_2,
					ERTS_SCHED_DIRTY_IO,
					am_erts_debug,
					am_dirty_io,
					2);
		break;
	    case am_dirty_cpu:
		argv[0] = arg1;
		argv[1] = eint;
		ret = erts_schedule_bif(c_p,
					argv,
					I,
					erts_debug_dirty_cpu_2,
					ERTS_SCHED_DIRTY_CPU,
					am_erts_debug,
					am_dirty_cpu,
					2);
		break;
	    case am_normal:
		argv[0] = am_normal;
		argv[1] = arg1;
		argv[2] = eint;
		ret = erts_schedule_bif(c_p,
					argv,
					I,
					erts_debug_dirty_3,
					ERTS_SCHED_NORMAL,
					am_erts_debug,
					am_dirty,
					3);
		break;
	    default:
		goto badarg;
	    }
	}
    }
    else if (ERTS_IS_ATOM_STR("ready_wait6_done", arg1)) {
	ERTS_DECL_AM(ready);
	ERTS_DECL_AM(done);
	dirty_send_message(c_p, arg2, AM_ready);
	ms_wait(c_p, make_small(6000), 0);
	dirty_send_message(c_p, arg2, AM_done);
	ERTS_BIF_PREP_RET(ret, am_ok);
    }
    else if (ERTS_IS_ATOM_STR("alive_waitexiting", arg1)) {
	Process *real_c_p = erts_proc_shadow2real(c_p);
	Eterm *hp, *hp2;
	Uint sz;
	int i;
	ErtsSchedulerData *esdp = erts_proc_sched_data(c_p);
        int dirty_io = esdp->type == ERTS_SCHED_DIRTY_IO;

	if (ERTS_PROC_IS_EXITING(real_c_p))
	    goto badarg;
	dirty_send_message(c_p, arg2, am_alive);

	/* Wait until dead */
	while (!ERTS_PROC_IS_EXITING(real_c_p)) {
            if (dirty_io)
                ms_wait(c_p, make_small(100), 0);
            else
                erts_thr_yield();
        }

	ms_wait(c_p, make_small(1000), 0);

	/* Should still be able to allocate memory */
	hp = HAlloc(c_p, 3); /* Likely on heap */
	sz = 10000;
	hp2 = HAlloc(c_p, sz); /* Likely in heap fragment */
	*hp2 = make_pos_bignum_header(sz);
	for (i = 1; i < sz; i++)
	    hp2[i] = (Eterm) 4711;
	ERTS_BIF_PREP_RET(ret, TUPLE2(hp, am_ok, make_big(hp2)));
    }
    else {
    badarg:
	ERTS_BIF_PREP_ERROR(ret, c_p, BADARG);
    }
    return ret;
}
Example #27
0
/* 
   You have to have loaded the driver and the pid state 
   is LOADED or AWAIT_LOAD. You will be removed from the list
   regardless of driver state.
   If the driver is loaded by someone else to, return is
   {ok, pending_process}
   If the driver is loaded but locked by a port, return is
   {ok, pending_driver}
   If the driver is loaded and free to unload (you're the last holding it)
   {ok, unloaded}
   If it's not loaded or not loaded by you
   {error, not_loaded} or {error, not_loaded_by_you}

   Internally, if its in state UNLOADING, just return {ok, pending_driver} and
   remove/decrement this pid (which should be an LOADED tagged one).
   If the state is RELOADING, this pid should be in list as LOADED tagged, 
   only AWAIT_LOAD would be possible but not allowed for unloading, remove it 
   and, if the last LOADED tagged, change from RELOAD to UNLOAD and notify
   any AWAIT_LOAD-waiters with {'DOWN', ref(), driver, name(), load_cancelled}
   If the driver made itself permanent, {'UP', ref(), driver, name(), permanent}
*/
Eterm erl_ddll_try_unload_2(BIF_ALIST_2)
{
    Eterm name_term = BIF_ARG_1;
    Eterm options = BIF_ARG_2;
    char *name = NULL;
    Eterm ok_term = NIL;
    Eterm soft_error_term = NIL;
    erts_driver_t *drv;
    DE_Handle *dh;
    DE_ProcEntry *pe;
    Eterm *hp;
    Eterm t;
    int monitor = 0;
    Eterm l;
    int kill_ports = 0;

    erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);

    for(l = options; is_list(l); l =  CDR(list_val(l))) {
	Eterm opt = CAR(list_val(l));
	Eterm *tp;
	if (is_not_tuple(opt)) {
	    if (opt == am_kill_ports) {
		kill_ports = 1;
		continue;
	    } else {
		goto error;
	    }
	}
	tp = tuple_val(opt);
	if (*tp != make_arityval(2) || tp[1] != am_monitor) {
	    goto error;
	}
	if (tp[2] == am_pending_driver) { 
	    monitor = 1;
	} else if (tp[2] == am_pending) {
	    monitor = 2;
	} else {
	    goto error;
	}
    }
    if (is_not_nil(l)) {
	goto error;
    }

    if ((name = pick_list_or_atom(name_term)) == NULL) {
	goto error;
    }

    lock_drv_list();

    if ((drv = lookup_driver(name)) == NULL) {
	soft_error_term = am_not_loaded;
	goto soft_error;
    }

    if (drv->handle == NULL) {
	soft_error_term = am_linked_in_driver;
	goto soft_error;
    } else if (drv->handle->status == ERL_DE_PERMANENT) {
	soft_error_term = am_permanent;
	goto soft_error;
    }	
    dh = drv->handle;
    if (dh->flags & ERL_DE_FL_KILL_PORTS) {
	kill_ports = 1;
    }
    if ((pe = find_proc_entry(dh, BIF_P, ERL_DE_PROC_LOADED)) == NULL) {
	if (num_procs(dh, ERL_DE_PROC_LOADED) > 0) {
	    soft_error_term = am_not_loaded_by_this_process;
	    goto soft_error;
	}
    } else {
	remove_proc_entry(dh, pe);
	if (!(pe->flags & ERL_DE_FL_DEREFERENCED)) {
	    erts_ddll_dereference_driver(dh);
	}
	erts_free(ERTS_ALC_T_DDLL_PROCESS, pe);
    }
    if (num_procs(dh, ERL_DE_PROC_LOADED) > 0) {
	ok_term = am_pending_process;
	--monitor;
	goto done;
    }
    if (dh->status == ERL_DE_RELOAD ||
	dh->status == ERL_DE_FORCE_RELOAD) {
	notify_all(dh, drv->name, 
		   ERL_DE_PROC_AWAIT_LOAD, am_DOWN, am_load_cancelled);
	erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_full_path);
	erts_free(ERTS_ALC_T_DDLL_HANDLE,dh->reload_driver_name);
	dh->reload_full_path = dh->reload_driver_name = NULL; 
	dh->reload_flags = 0;
    } 
    if (erts_atomic32_read_nob(&dh->port_count) > 0) {
	++kill_ports;
    }
    dh->status = ERL_DE_UNLOAD;
    ok_term = am_pending_driver;
done:
    assert_drv_list_rwlocked();
    if (kill_ports > 1) {
	/* Avoid closing the driver by referencing it */
	erts_ddll_reference_driver(dh);
	dh->status = ERL_DE_FORCE_UNLOAD;
	unlock_drv_list();
	kill_ports_driver_unloaded(dh);
	lock_drv_list(); 
	erts_ddll_dereference_driver(dh);
    } 

    erts_ddll_reference_driver(dh);
    unlock_drv_list();
    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    lock_drv_list();
    erts_ddll_dereference_driver(dh);
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    BIF_P->flags |= F_USING_DDLL;
    if (monitor > 0) {
	Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_UNLOAD);
	hp = HAlloc(BIF_P, 4);
	t = TUPLE3(hp, am_ok, ok_term, mref);
    } else {
	hp = HAlloc(BIF_P, 3);
	t = TUPLE2(hp, am_ok, ok_term);
    }
    if (kill_ports > 1) {
	ERTS_BIF_CHK_EXITED(BIF_P); /* May be exited by port killing */
    }
    unlock_drv_list();
    BIF_RET(t);
 
soft_error:
    unlock_drv_list();
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    hp = HAlloc(BIF_P, 3);
    t = TUPLE2(hp, am_error, soft_error_term);
    BIF_RET(t);
 
 error: /* No lock fiddling before going here */
    assert_drv_list_not_locked();
    if (name != NULL) {
	erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    }
    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    BIF_ERROR(BIF_P, BADARG);
}
Example #28
0
static void
setup_reference_table(void)
{
    ErlHeapFragment *hfp;
    DistEntry *dep;
    HashInfo hi;
    int i;
    Eterm heap[3];

    inserted_bins = NULL;

    hash_get_info(&hi, &erts_node_table);
    referred_nodes = erts_alloc(ERTS_ALC_T_NC_TMP,
				hi.objs*sizeof(ReferredNode));
    no_referred_nodes = 0;
    hash_foreach(&erts_node_table, init_referred_node, NULL);
    ASSERT(no_referred_nodes == hi.objs);

    hash_get_info(&hi, &erts_dist_table);
    referred_dists = erts_alloc(ERTS_ALC_T_NC_TMP,
				hi.objs*sizeof(ReferredDist));
    no_referred_dists = 0;
    hash_foreach(&erts_dist_table, init_referred_dist, NULL);
    ASSERT(no_referred_dists == hi.objs);

    /* Go through the hole system, and build a table of all references
       to ErlNode and DistEntry structures */

    insert_node(erts_this_node,
		SYSTEM_REF,
		TUPLE2(&heap[0], AM_system, am_undefined));

#ifdef HYBRID
    /* Insert Heap */
    insert_offheap(&erts_global_offheap,
		   HEAP_REF,
		   TUPLE2(&heap[0], AM_processes, am_undefined));
#endif

    /* Insert all processes */
    for (i = 0; i < erts_max_processes; i++)
	if (process_tab[i]) {
	    /* Insert Heap */
	    insert_offheap(&(process_tab[i]->off_heap),
			   HEAP_REF,
			   process_tab[i]->id);
	    /* Insert message buffers */
	    for(hfp = process_tab[i]->mbuf; hfp; hfp = hfp->next)
		insert_offheap(&(hfp->off_heap),
			       HEAP_REF,
			       process_tab[i]->id);
#ifdef ERTS_SMP
	    /* Insert msg msg buffers */
	    {
		ErlMessage *msg;
		for (msg = process_tab[i]->msg.first; msg; msg = msg->next)
		    if (msg->bp)
			insert_offheap(&(msg->bp->off_heap),
				       HEAP_REF,
				       process_tab[i]->id);
		for (msg = process_tab[i]->msg_inq.first; msg; msg = msg->next)
		    if (msg->bp)
			insert_offheap(&(msg->bp->off_heap),
				       HEAP_REF,
				       process_tab[i]->id);
	    }
#endif
	    /* Insert links */
	    if(process_tab[i]->nlinks)
		insert_links(process_tab[i]->nlinks, process_tab[i]->id);
	    if(process_tab[i]->monitors)
		insert_monitors(process_tab[i]->monitors, process_tab[i]->id);
	    /* Insert controller */
	    {
		DistEntry *dep = ERTS_PROC_GET_DIST_ENTRY(process_tab[i]);
		if (dep)
		    insert_dist_entry(dep, CTRL_REF, process_tab[i]->id, 0);
	    }
	}
    
#ifdef ERTS_SMP
    erts_foreach_sys_msg_in_q(insert_sys_msg);
#endif

    /* Insert all ports */
    for (i = 0; i < erts_max_ports; i++) {
	if (erts_port[i].status & ERTS_PORT_SFLGS_DEAD)
	    continue;

	/* Insert links */
	if(erts_port[i].nlinks)
	    insert_links(erts_port[i].nlinks, erts_port[i].id);
	/* Insert port data */
	for(hfp = erts_port[i].bp; hfp; hfp = hfp->next)
	    insert_offheap(&(hfp->off_heap), HEAP_REF, erts_port[i].id);
	/* Insert controller */
	if (erts_port[i].dist_entry)
	    insert_dist_entry(erts_port[i].dist_entry,
			      CTRL_REF,
			      erts_port[i].id,
			      0);
    }

    { /* Add binaries stored elsewhere ... */
	ErlOffHeap oh;
	ProcBin pb[2] = {{0},{0}};
	ProcBin *mso = NULL;
	int i = 0;
	Binary *default_match_spec;
	Binary *default_meta_match_spec;

	/* Only the ProcBin members val and next will be inspected
	   (by insert_offheap()) */
#undef  ADD_BINARY
#define ADD_BINARY(Bin)					\
	if ((Bin)) {					\
	    pb[i].val = (Bin);				\
	    pb[i].next = mso;				\
	    mso = &pb[i];				\
	    i++;					\
	}

	erts_get_default_trace_pattern(NULL,
				       &default_match_spec,
				       &default_meta_match_spec,
				       NULL,
				       NULL);

	ADD_BINARY(default_match_spec);
	ADD_BINARY(default_meta_match_spec);

	oh.mso = mso;
	oh.externals = NULL;
#ifndef HYBRID /* FIND ME! */
	oh.funs = NULL;
#endif
	insert_offheap(&oh, BIN_REF, AM_match_spec);
#undef  ADD_BINARY
    }

    /* Insert all dist links */

    for(dep = erts_visible_dist_entries; dep; dep = dep->next) {
	if(dep->nlinks)
	    insert_links2(dep->nlinks, dep->sysname);
	if(dep->node_links)
	    insert_links(dep->node_links, dep->sysname);
	if(dep->monitors)
	    insert_monitors(dep->monitors, dep->sysname);
    }

    for(dep = erts_hidden_dist_entries; dep; dep = dep->next) {
	if(dep->nlinks)
	    insert_links2(dep->nlinks, dep->sysname);
	if(dep->node_links)
	    insert_links(dep->node_links, dep->sysname);
	if(dep->monitors)
	    insert_monitors(dep->monitors, dep->sysname);
    }

    /* Not connected dist entries should not have any links,
       but inspect them anyway */
    for(dep = erts_not_connected_dist_entries; dep; dep = dep->next) {
	if(dep->nlinks)
	    insert_links2(dep->nlinks, dep->sysname);
	if(dep->node_links)
	    insert_links(dep->node_links, dep->sysname);
	if(dep->monitors)
	    insert_monitors(dep->monitors, dep->sysname);
    }

    /* Insert all ets tables */
    erts_db_foreach_table(insert_ets_table, NULL);

    /* Insert all bif timers */
    erts_bif_timer_foreach(insert_bif_timer, NULL);

    /* Insert node table (references to dist) */
    hash_foreach(&erts_node_table, insert_erl_node, NULL);
}
Example #29
0
/*
 * Try to load. If the driver is OK, add as LOADED.  If the driver is
 * UNLOAD, possibly change to reload and add as LOADED, 
 * there should be no other
 * LOADED tagged pid's.  If the driver is RELOAD then add/increment as
 * LOADED (should be some LOADED pid).  If the driver is not present,
 * really load and add as LOADED {ok,loaded} {ok,pending_driver}
 * {error, permanent} {error,load_error()}
 */
BIF_RETTYPE erl_ddll_try_load_3(BIF_ALIST_3)
{
    Eterm path_term = BIF_ARG_1;
    Eterm name_term = BIF_ARG_2;
    Eterm options = BIF_ARG_3;
    char *path = NULL;
    Sint path_len;
    char *name = NULL;
    DE_Handle *dh;
    erts_driver_t *drv;
    int res;
    Eterm soft_error_term = NIL;
    Eterm ok_term = NIL;
    Eterm *hp;
    Eterm t;
    int monitor = 0;
    int reload = 0;
    Eterm l;
    Uint flags = 0;
    int kill_ports = 0;
    int do_build_load_error = 0;
    int build_this_load_error = 0;
    int encoding;

    for(l = options; is_list(l); l =  CDR(list_val(l))) {
	Eterm opt = CAR(list_val(l));
	Eterm *tp;
	if (is_not_tuple(opt)) {
	    goto error;
	}
	tp = tuple_val(opt);
	if (*tp != make_arityval(2) || is_not_atom(tp[1])) {
	    goto error;
	}
	switch (tp[1]) {
	case am_driver_options:
	    {
		Eterm ll;
		for(ll = tp[2]; is_list(ll); ll = CDR(list_val(ll))) {
		    Eterm dopt = CAR(list_val(ll));
		    if (dopt == am_kill_ports) {
			flags |= ERL_DE_FL_KILL_PORTS;
		    } else {
			goto error;
		    }
		}
		if (is_not_nil(ll)) {
		    goto error;
		}
	    }
	    break;
	case am_monitor:
	    if (tp[2] == am_pending_driver) {
		monitor = 1;
	    } else if (tp[2] == am_pending ) {
		monitor = 2;
	    } else {
		goto error;
	    }
	    break;
	case am_reload:
	    if (tp[2] == am_pending_driver) {
		reload = 1;
	    } else if (tp[2] == am_pending ) {
		reload = 2;
	    } else {
		goto error;
	    }
	    break;
	default:
	    goto error;
	}
    }
    if (is_not_nil(l)) {
	goto error;
    }


    if ((name = pick_list_or_atom(name_term)) == NULL) {
	goto error;
    }

    encoding = erts_get_native_filename_encoding();
    if (encoding == ERL_FILENAME_WIN_WCHAR) {
        /* Do not convert the lib name to utf-16le yet, do that in win32 specific code */
        /* since lib_name is used in error messages */
        encoding = ERL_FILENAME_UTF8;
    }
    path = erts_convert_filename_to_encoding(path_term, NULL, 0,
					     ERTS_ALC_T_DDLL_TMP_BUF, 1, 0,
					     encoding, &path_len,
					     sys_strlen(name) + 2); /* might need path separator */
    if (!path) {
	goto error;
    }
    ASSERT(path_len > 0 && path[path_len-1] == 0);
    while (--path_len > 0 && (path[path_len-1] == '\\' || path[path_len-1] == '/'))
	;
    path[path_len++] = '/';
    sys_strcpy(path+path_len,name);

    erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
    lock_drv_list();
    if ((drv = lookup_driver(name)) != NULL) {
	if (drv->handle == NULL) {
	    /* static_driver */
	    soft_error_term = am_linked_in_driver;
	    goto soft_error;
	} else {
	    dh = drv->handle;
	    if (dh->status == ERL_DE_OK) {
		int is_last = is_last_user(dh, BIF_P);
		if (reload == 1 && !is_last) {
		    /*Want reload if no other users, 
		      but there are others...*/
		    soft_error_term = am_pending_process;
		    goto soft_error;
		} 
		if (reload != 0) {
		    DE_ProcEntry *old;
		    if ((dh->flags & ERL_FL_CONSISTENT_MASK) != 
			(flags &  ERL_FL_CONSISTENT_MASK)) {
			soft_error_term = am_inconsistent;
			goto soft_error;
		    }
		    if ((old = find_proc_entry(dh, BIF_P,
					       ERL_DE_PROC_LOADED)) ==
			NULL) {
			soft_error_term = am_not_loaded_by_this_process;
			goto soft_error;
		    } else {
			remove_proc_entry(dh, old);
			erts_ddll_dereference_driver(dh);
			erts_free(ERTS_ALC_T_DDLL_PROCESS, old);
		    }
		    /* Reload requested and granted */
		    dereference_all_processes(dh);
		    set_driver_reloading(dh, BIF_P, path, name, flags);
		    if (dh->flags & ERL_DE_FL_KILL_PORTS) {
			kill_ports = 1;
		    }
		    ok_term = (reload == 1) ? am_pending_driver : 
			am_pending_process;
		} else {
		    /* Already loaded and healthy (might be by me) */
		    if (sys_strcmp(dh->full_path, path) || 
			(dh->flags & ERL_FL_CONSISTENT_MASK) != 
			(flags &  ERL_FL_CONSISTENT_MASK)) {
			soft_error_term = am_inconsistent;
			goto soft_error;
		    }
		    add_proc_loaded(dh, BIF_P);
		    erts_ddll_reference_driver(dh);
		    monitor = 0;
		    ok_term = mkatom("already_loaded");
		}
	    } else if (dh->status == ERL_DE_UNLOAD ||
		       dh->status == ERL_DE_FORCE_UNLOAD) {
		/* pending driver */
		if (reload != 0) {
		    soft_error_term = am_not_loaded_by_this_process;
		    goto soft_error;
		} 
		if (sys_strcmp(dh->full_path, path) || 
		    (dh->flags & ERL_FL_CONSISTENT_MASK) != 
		    (flags &  ERL_FL_CONSISTENT_MASK)) {
		    soft_error_term = am_inconsistent;
		    goto soft_error;
		}
		dh->status = ERL_DE_OK;
		notify_all(dh, drv->name, 
			   ERL_DE_PROC_AWAIT_UNLOAD, am_UP, 
			   am_unload_cancelled);
		add_proc_loaded(dh, BIF_P);
		erts_ddll_reference_driver(dh);
		monitor = 0;
		ok_term = mkatom("already_loaded");
	    } else if (dh->status == ERL_DE_RELOAD ||
		       dh->status == ERL_DE_FORCE_RELOAD) {
		if (reload != 0) {
		    soft_error_term = am_pending_reload;
		    goto soft_error;
		}
		if (sys_strcmp(dh->reload_full_path, path) || 
		    (dh->reload_flags & ERL_FL_CONSISTENT_MASK) != 
		        (flags &  ERL_FL_CONSISTENT_MASK)) {
		    soft_error_term = am_inconsistent;
		    goto soft_error;
		}
		/* Load of granted unload... */
		/* Don't reference, will happen after reload */
		add_proc_loaded_deref(dh, BIF_P);
		++monitor;
		ok_term = am_pending_driver;
	    } else { /* ERL_DE_PERMANENT */
		soft_error_term = am_permanent;
		goto soft_error;
	    }
	}
    } else { /* driver non-existing */
	if (reload != 0) {
	    soft_error_term = am_not_loaded;
	    goto soft_error;
	} 
	if ((res = load_driver_entry(&dh, path, name)) !=  ERL_DE_NO_ERROR) {
	    build_this_load_error = res;
	    do_build_load_error = 1;
	    soft_error_term = am_undefined;
	    goto soft_error;
	} else {
	    dh->flags = flags;
	    add_proc_loaded(dh, BIF_P);
	    first_ddll_reference(dh);
	    monitor = 0;
	    ok_term = mkatom("loaded");
	}
    }
    assert_drv_list_rwlocked();
    if (kill_ports) {
 	/* Avoid closing the driver by referencing it */
	erts_ddll_reference_driver(dh);
	ASSERT(dh->status == ERL_DE_RELOAD);
	dh->status = ERL_DE_FORCE_RELOAD;
	unlock_drv_list();
	kill_ports_driver_unloaded(dh);
	/* Dereference, eventually causing driver destruction */
	lock_drv_list(); 
	erts_ddll_dereference_driver(dh);
    } 

    erts_ddll_reference_driver(dh);
    unlock_drv_list();
    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    lock_drv_list();
    erts_ddll_dereference_driver(dh);

    BIF_P->flags |= F_USING_DDLL;
    if (monitor) {
	Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_LOAD);
	hp = HAlloc(BIF_P, 4);
	t = TUPLE3(hp, am_ok, ok_term, mref);
    } else {
	hp = HAlloc(BIF_P, 3);
	t = TUPLE2(hp, am_ok, ok_term);
    }
    unlock_drv_list();
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
    BIF_RET(t);
 soft_error:
    unlock_drv_list();
    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    if (do_build_load_error) {
	soft_error_term = build_load_error(BIF_P, build_this_load_error);
    }

    hp = HAlloc(BIF_P, 3);
    t = TUPLE2(hp, am_error, soft_error_term);
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
    BIF_RET(t);
 error:
    assert_drv_list_not_locked();
    ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
    if (path != NULL) {
	erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
    }
    if (name != NULL) {
	erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    }
    BIF_ERROR(BIF_P, BADARG);
}
Example #30
0
Eterm
load_module_2(BIF_ALIST_2)
{
    Eterm   reason;
    Eterm*  hp;
    int      i;
    int      sz;
    byte*    code;
    int trace_pattern_is_on;
    Binary *match_spec;
    Binary *meta_match_spec;
    struct trace_pattern_flags trace_pattern_flags;
    Eterm meta_tracer_pid;
    Eterm res;
    byte* temp_alloc = NULL;

    if (is_not_atom(BIF_ARG_1)) {
    error:
	erts_free_aligned_binary_bytes(temp_alloc);
	BIF_ERROR(BIF_P, BADARG);
    }
    if ((code = erts_get_aligned_binary_bytes(BIF_ARG_2, &temp_alloc)) == NULL) {
	goto error;
    }
    erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
    erts_smp_block_system(0);

    erts_export_consolidate();

    hp = HAlloc(BIF_P, 3);
    sz = binary_size(BIF_ARG_2);
    if ((i = erts_load_module(BIF_P, 0,
			      BIF_P->group_leader, &BIF_ARG_1, code, sz)) < 0) { 
	switch (i) {
	case -1: reason = am_badfile; break; 
	case -2: reason = am_nofile; break;
	case -3: reason = am_not_purged; break;
	case -4:
	    reason = am_atom_put("native_code", sizeof("native_code")-1);
	    break;
	default: reason = am_badfile; break;
	}
	res = TUPLE2(hp, am_error, reason);
	goto done;
    }

    erts_get_default_trace_pattern(&trace_pattern_is_on,
				   &match_spec,
				   &meta_match_spec,
				   &trace_pattern_flags,
				   &meta_tracer_pid);
    if (trace_pattern_is_on) {
	Eterm mfa[1];
	mfa[0] = BIF_ARG_1;
	(void) erts_set_trace_pattern(mfa, 1, 
				      match_spec, 
				      meta_match_spec,
				      1, trace_pattern_flags, 
				      meta_tracer_pid);
    }

    res = TUPLE2(hp, am_module, BIF_ARG_1);

 done:
    erts_free_aligned_binary_bytes(temp_alloc);
    erts_smp_release_system();
    erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);

    BIF_RET(res);
}