Ejemplo n.º 1
0
ErlDrvMutex *
erl_drv_mutex_create(char *name)
{
#ifdef USE_THREADS
    ErlDrvMutex *dmtx = erts_alloc_fnf(ERTS_ALC_T_DRV_MTX,
				       (sizeof(ErlDrvMutex)
					+ (name ? sys_strlen(name) + 1 : 0)));
    if (dmtx) {
	if (ethr_mutex_init(&dmtx->mtx) != 0) {
	    erts_free(ERTS_ALC_T_DRV_MTX, (void *) dmtx);
	    dmtx = NULL;
	}
	else if (!name)
	    dmtx->name = no_name;
	else {
	    dmtx->name = ((char *) dmtx) + sizeof(ErlDrvMutex);
	    sys_strcpy(dmtx->name, name);
	}
    }
    return dmtx;
#else
    return (ErlDrvMutex *) NULL;
#endif
}
Ejemplo n.º 2
0
ErlDrvRWLock *
erl_drv_rwlock_create(char *name)
{
#ifdef USE_THREADS
    ErlDrvRWLock *drwlck = erts_alloc_fnf(ERTS_ALC_T_DRV_RWLCK,
					  (sizeof(ErlDrvRWLock)
					   + (name ? sys_strlen(name) + 1 : 0)));
    if (drwlck) {
	if (ethr_rwmutex_init(&drwlck->rwmtx) != 0) {
	    erts_free(ERTS_ALC_T_DRV_RWLCK, (void *) drwlck);
	    drwlck = NULL;
	}
	else if (!name)
	    drwlck->name = no_name;
	else {
	    drwlck->name = ((char *) drwlck) + sizeof(ErlDrvRWLock);
	    sys_strcpy(drwlck->name, name);
	}
    }
    return drwlck;
#else
    return (ErlDrvRWLock *) NULL;
#endif
}
Ejemplo n.º 3
0
ErlDrvCond *
erl_drv_cond_create(char *name)
{
#ifdef USE_THREADS
    ErlDrvCond *dcnd = erts_alloc_fnf(ERTS_ALC_T_DRV_CND,
				      (sizeof(ErlDrvCond)
				       + (name ? sys_strlen(name) + 1 : 0)));
    if (dcnd) {
	if (ethr_cond_init(&dcnd->cnd) != 0) {
	    erts_free(ERTS_ALC_T_DRV_CND, (void *) dcnd);
	    dcnd = NULL;
	}
	else if (!name)
	    dcnd->name = no_name;
	else {
	    dcnd->name = ((char *) dcnd) + sizeof(ErlDrvCond);
	    sys_strcpy(dcnd->name, name);
	}
    }
    return dcnd;
#else
    return (ErlDrvCond *) NULL;
#endif
}
Ejemplo n.º 4
0
Archivo: erl_nif.c Proyecto: a5an0/otp
int enif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom,
			    ErlNifCharEncoding enc)
{
    return enif_make_existing_atom_len(env, name, sys_strlen(name), atom, enc);
}
Ejemplo n.º 5
0
Archivo: erl_nif.c Proyecto: a5an0/otp
ERL_NIF_TERM enif_make_atom(ErlNifEnv* env, const char* name)
{
    return enif_make_atom_len(env, name, sys_strlen(name));
}
Ejemplo n.º 6
0
Archivo: erl_nif.c Proyecto: a5an0/otp
BIF_RETTYPE load_nif_2(BIF_ALIST_2)
{
    static const char bad_lib[] = "bad_lib";
    static const char reload[] = "reload";
    static const char upgrade[] = "upgrade";
    char* lib_name = NULL;
    void* handle = NULL;
    void* init_func;
    ErlNifEntry* entry = NULL;
    ErlNifEnv env;
    int len, i, err;
    Module* mod;
    Eterm mod_atom;
    Eterm f_atom;
    BeamInstr* caller;
    ErtsSysDdllError errdesc = ERTS_SYS_DDLL_ERROR_INIT;
    Eterm ret = am_ok;
    int veto;
    struct erl_module_nif* lib = NULL;

    len = list_length(BIF_ARG_1);
    if (len < 0) {
	BIF_ERROR(BIF_P, BADARG);
    }
    lib_name = (char *) erts_alloc(ERTS_ALC_T_TMP, len + 1);

    if (intlist_to_buf(BIF_ARG_1, lib_name, len) != len) {
	erts_free(ERTS_ALC_T_TMP, lib_name);
	BIF_ERROR(BIF_P, BADARG);
    }
    lib_name[len] = '\0';

    /* Block system (is this the right place to do it?) */
    erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
    erts_smp_thr_progress_block();

    /* Find calling module */
    ASSERT(BIF_P->current != NULL);
    ASSERT(BIF_P->current[0] == am_erlang
	   && BIF_P->current[1] == am_load_nif 
	   && BIF_P->current[2] == 2);
    caller = find_function_from_pc(BIF_P->cp);
    ASSERT(caller != NULL);
    mod_atom = caller[0];
    ASSERT(is_atom(mod_atom));
    mod=erts_get_module(mod_atom);
    ASSERT(mod != NULL);

    if (!in_area(caller, mod->code, mod->code_length)) {
	ASSERT(in_area(caller, mod->old_code, mod->old_code_length));

	ret = load_nif_error(BIF_P, "old_code", "Calling load_nif from old "
			     "module '%T' not allowed", mod_atom);
    }    
    else if ((err=erts_sys_ddll_open2(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) {
	const char slogan[] = "Failed to load NIF library";
	if (strstr(errdesc.str, lib_name) != NULL) {
	    ret = load_nif_error(BIF_P, "load_failed", "%s: '%s'", slogan, errdesc.str);
	}
	else {
	    ret = load_nif_error(BIF_P, "load_failed", "%s %s: '%s'", slogan, lib_name, errdesc.str);
	}
    }
    else if (erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) {
	ret  = load_nif_error(BIF_P, bad_lib, "Failed to find library init"
			      " function: '%s'", errdesc.str);
	
    }
    else if ((add_taint(mod_atom),
	      (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) {
	ret = load_nif_error(BIF_P, bad_lib, "Library init-call unsuccessful");
    }
    else if (entry->major != ERL_NIF_MAJOR_VERSION
	     || entry->minor > ERL_NIF_MINOR_VERSION) {
	
	ret = load_nif_error(BIF_P, bad_lib, "Library version (%d.%d) not compatible (with %d.%d).",
			     entry->major, entry->minor, ERL_NIF_MAJOR_VERSION, ERL_NIF_MINOR_VERSION);
    }   
    else if (entry->minor >= 1
	     && sys_strcmp(entry->vm_variant, ERL_NIF_VM_VARIANT) != 0) {
	ret = load_nif_error(BIF_P, bad_lib, "Library (%s) not compiled for "
			     "this vm variant (%s).",
			     entry->vm_variant, ERL_NIF_VM_VARIANT);
    }
    else if (!erts_is_atom_str((char*)entry->name, mod_atom)) {
	ret = load_nif_error(BIF_P, bad_lib, "Library module name '%s' does not"
			     " match calling module '%T'", entry->name, mod_atom);
    }
    else {
	/*erts_fprintf(stderr, "Found module %T\r\n", mod_atom);*/
    
	for (i=0; i < entry->num_of_funcs && ret==am_ok; i++) {
	    BeamInstr** code_pp;
	    ErlNifFunc* f = &entry->funcs[i];
	    if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom)
		|| (code_pp = get_func_pp(mod->code, f_atom, f->arity))==NULL) { 
		ret = load_nif_error(BIF_P,bad_lib,"Function not found %T:%s/%u",
				     mod_atom, f->name, f->arity);
	    }    
	    else if (code_pp[1] - code_pp[0] < (5+3)) {
		ret = load_nif_error(BIF_P,bad_lib,"No explicit call to load_nif"
				     " in module (%T:%s/%u to small)",
				     mod_atom, entry->funcs[i].name, entry->funcs[i].arity);
	    }
	    /*erts_fprintf(stderr, "Found NIF %T:%s/%u\r\n",
			 mod_atom, entry->funcs[i].name, entry->funcs[i].arity);*/
	}
    }

    if (ret != am_ok) {
	goto error;
    }

    /* Call load, reload or upgrade:
     */


    lib = erts_alloc(ERTS_ALC_T_NIF, sizeof(struct erl_module_nif));
    lib->handle = handle;
    lib->entry = entry;
    erts_refc_init(&lib->rt_cnt, 0);
    erts_refc_init(&lib->rt_dtor_cnt, 0);
    lib->mod = mod;
    env.mod_nif = lib;
    if (mod->nif != NULL) { /* Reload */
	int k;
        lib->priv_data = mod->nif->priv_data;

	ASSERT(mod->nif->entry != NULL);
	if (entry->reload == NULL) {
	    ret = load_nif_error(BIF_P,reload,"Reload not supported by this NIF library.");
	    goto error;
	}
	/* Check that no NIF is removed */
	for (k=0; k < mod->nif->entry->num_of_funcs; k++) {
	    ErlNifFunc* old_func = &mod->nif->entry->funcs[k];
	    for (i=0; i < entry->num_of_funcs; i++) {
		if (old_func->arity == entry->funcs[i].arity
		    && sys_strcmp(old_func->name, entry->funcs[i].name) == 0) {			   
		    break;
		}
	    }
	    if (i == entry->num_of_funcs) {
		ret = load_nif_error(BIF_P,reload,"Reloaded library missing "
				     "function %T:%s/%u\r\n", mod_atom,
				     old_func->name, old_func->arity);
		goto error;
	    }
	}       
	erts_pre_nif(&env, BIF_P, lib);
	veto = entry->reload(&env, &lib->priv_data, BIF_ARG_2);
	erts_post_nif(&env);
	if (veto) {
	    ret = load_nif_error(BIF_P, reload, "Library reload-call unsuccessful.");
	}
	else {
	    mod->nif->entry = NULL; /* to prevent 'unload' callback */
	    erts_unload_nif(mod->nif);
	}
    }
    else {
	lib->priv_data = NULL;
	if (mod->old_nif != NULL) { /* Upgrade */
	    void* prev_old_data = mod->old_nif->priv_data;
	    if (entry->upgrade == NULL) {
		ret = load_nif_error(BIF_P, upgrade, "Upgrade not supported by this NIF library.");
		goto error;
	    }
	    erts_pre_nif(&env, BIF_P, lib);
	    veto = entry->upgrade(&env, &lib->priv_data, &mod->old_nif->priv_data, BIF_ARG_2);
	    erts_post_nif(&env);
	    if (veto) {
		mod->old_nif->priv_data = prev_old_data;
		ret = load_nif_error(BIF_P, upgrade, "Library upgrade-call unsuccessful.");
	    }
	    /*else if (mod->old_nif->priv_data != prev_old_data) {
		refresh_cached_nif_data(mod->old_code, mod->old_nif);
	    }*/
	}
	else if (entry->load != NULL) { /* Initial load */
	    erts_pre_nif(&env, BIF_P, lib);
	    veto = entry->load(&env, &lib->priv_data, BIF_ARG_2);
	    erts_post_nif(&env);
	    if (veto) {
		ret = load_nif_error(BIF_P, "load", "Library load-call unsuccessful.");
	    }
	}
    }
    if (ret == am_ok) {
	/*
	** Everything ok, patch the beam code with op_call_nif
	*/
        mod->nif = lib; 
	for (i=0; i < entry->num_of_funcs; i++)
	{
	    BeamInstr* code_ptr;
	    erts_atom_get(entry->funcs[i].name, sys_strlen(entry->funcs[i].name), &f_atom); 
	    code_ptr = *get_func_pp(mod->code, f_atom, entry->funcs[i].arity); 
	    
	    if (code_ptr[1] == 0) {
		code_ptr[5+0] = (BeamInstr) BeamOp(op_call_nif);
	    }
	    else { /* Function traced, patch the original instruction word */
		BpData** bps = (BpData**) code_ptr[1];
		BpData*  bp  = (BpData*) bps[erts_bp_sched2ix()];
	        bp->orig_instr = (BeamInstr) BeamOp(op_call_nif);
	    }	    
	    code_ptr[5+1] = (BeamInstr) entry->funcs[i].fptr;
	    code_ptr[5+2] = (BeamInstr) lib;
	}
    }
    else {
    error:
	ASSERT(ret != am_ok);
        if (lib != NULL) {
	    erts_free(ERTS_ALC_T_NIF, lib);
	}
	if (handle != NULL) {
	    erts_sys_ddll_close(handle);
	}
	erts_sys_ddll_free_error(&errdesc);
    }

    erts_smp_thr_progress_unblock();
    erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    erts_free(ERTS_ALC_T_TMP, lib_name);
    BIF_RET(ret);
}
Ejemplo n.º 7
0
Archivo: erl_nif.c Proyecto: a5an0/otp
static Eterm mkatom(const char *str)
{
    return am_atom_put(str, sys_strlen(str));
}
Ejemplo n.º 8
0
Archivo: erl_nif.c Proyecto: a5an0/otp
ERL_NIF_TERM enif_make_string(ErlNifEnv* env, const char* string,
			      ErlNifCharEncoding encoding)
{
    return enif_make_string_len(env, string, sys_strlen(string), encoding);
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
static int
write_trace_header(char *nodename, char *pid, char *hostname)
{
#ifdef DEBUG
    byte *startp;
#endif
    Uint16 entry_sz;
    Uint32 flags, n_len, h_len, p_len, hdr_prolog_len;
    int i, no, str_len;
    const char *str;
    struct {
	Uint32 gsec;
	Uint32 sec;
	Uint32 usec;
    } start_time;

    sys_gettimeofday(&last_tv);

    start_time.gsec = (Uint32) (last_tv.tv_sec / 1000000000);
    start_time.sec  = (Uint32) (last_tv.tv_sec % 1000000000);
    start_time.usec = (Uint32) last_tv.tv_usec;

    if (!MAKE_TBUF_SZ(3*UI32_SZ))
	return 0;

    flags = 0;
#ifdef ARCH_64
    flags |= ERTS_MT_64_BIT_FLAG;
#endif
    flags |= ERTS_MT_CRR_INFO;
#ifdef ERTS_CAN_TRACK_MALLOC
    flags |= ERTS_MT_SEG_CRR_INFO;
#endif

    /*
     * The following 3 ui32 words *always* have to come
     * first in the trace.
     */
    PUT_UI32(tracep, ERTS_MT_START_WORD);
    PUT_UI32(tracep, ERTS_MT_MAJOR_VSN);
    PUT_UI32(tracep, ERTS_MT_MINOR_VSN);

    n_len = sys_strlen(nodename);
    h_len = sys_strlen(hostname);
    p_len = sys_strlen(pid);
    hdr_prolog_len = (2*UI32_SZ
		      + 3*UI16_SZ
		      + 3*UI32_SZ
		      + 3*UI8_SZ
		      + n_len
		      + h_len
		      + p_len);

    if (!MAKE_TBUF_SZ(hdr_prolog_len))
	return 0;

    /*
     * New stuff can be added at the end the of header prolog
     * (EOHP). The reader should skip stuff at the end, that it
     * doesn't understand.
     */

#ifdef DEBUG
    startp = tracep;
#endif

    PUT_UI32(tracep, hdr_prolog_len);
    PUT_UI32(tracep, flags);
    PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
    PUT_UI16(tracep, ERTS_ALC_A_MAX);
    PUT_UI16(tracep, ERTS_ALC_N_MAX);

    PUT_UI32(tracep, start_time.gsec);
    PUT_UI32(tracep, start_time.sec);
    PUT_UI32(tracep, start_time.usec);

    PUT_UI8(tracep, (byte) n_len);
    sys_memcpy((void *) tracep, (void *) nodename, n_len);
    tracep += n_len;

    PUT_UI8(tracep, (byte) h_len);
    sys_memcpy((void *) tracep, (void *) hostname, h_len);
    tracep += h_len;

    PUT_UI8(tracep, (byte) p_len);
    sys_memcpy((void *) tracep, (void *) pid, p_len);
    tracep += p_len;

    ASSERT(startp + hdr_prolog_len == tracep);

    /*
     * EOHP
     */

    /*
     * All tags from here on should be followed by an Uint16 size
     * field containing the total size of the entry.
     *
     * New stuff can eigther be added at the end of an entry, or
     * as a new tagged entry. The reader should skip stuff at the
     * end, that it doesn't understand.
     */

    for (i = ERTS_ALC_A_MIN; i <= ERTS_ALC_A_MAX; i++) {
	Uint16 aflags = 0;

#ifndef ERTS_CAN_TRACK_MALLOC
	if (i != ERTS_ALC_A_SYSTEM)
#endif
	    aflags |= ERTS_MT_ALLCTR_USD_CRR_INFO;

	str = ERTS_ALC_A2AD(i);
	ASSERT(str);
	str_len = sys_strlen(str);
	if (str_len >= (1 << 8)) {
	    disable_trace(1, "Excessively large allocator string", 0);
	    return 0;
	}

	entry_sz = UI8_SZ + 3*UI16_SZ + UI8_SZ;
	entry_sz += (erts_allctrs_info[i].alloc_util ? 2 : 1)*UI16_SZ;
	entry_sz += UI8_SZ + str_len;

	if (!MAKE_TBUF_SZ(entry_sz))
	    return 0;

#ifdef DEBUG
	startp = tracep;
#endif
	PUT_UI8(tracep, ERTS_MT_ALLOCATOR_HDR_TAG);
	PUT_UI16(tracep, entry_sz);
	PUT_UI16(tracep, aflags);
	PUT_UI16(tracep, (Uint16) i);
	PUT_UI8( tracep, (byte) str_len);
	sys_memcpy((void *) tracep, (void *) str, str_len);
	tracep += str_len;
	if (erts_allctrs_info[i].alloc_util) {
	    PUT_UI8(tracep, 2);
	    PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
	    PUT_UI16(tracep, ERTS_ALC_A_SYSTEM);
	}
	else {
	    PUT_UI8(tracep, 1);
	    switch (i) {
	    case ERTS_ALC_A_SYSTEM:
		PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
		break;
	    default:
		PUT_UI16(tracep, ERTS_MTRACE_SEGMENT_ID);
		break;
	    }
	}
	ASSERT(startp + entry_sz == tracep);
    }

    for (i = ERTS_ALC_N_MIN; i <= ERTS_ALC_N_MAX; i++) {
	Uint16 nflags = 0;
	str = ERTS_ALC_N2TD(i);
	ASSERT(str);

	str_len = sys_strlen(str);
	if (str_len >= (1 << 8)) {
	    disable_trace(1, "Excessively large type string", 0);
	    return 0;
	}

	no = ERTS_ALC_T2A(ERTS_ALC_N2T(i));
	if (!erts_allctrs_info[no].enabled)
	    no = ERTS_ALC_A_SYSTEM;
	ASSERT(ERTS_ALC_A_MIN <= no && no <= ERTS_ALC_A_MAX);

	entry_sz = UI8_SZ + 3*UI16_SZ + UI8_SZ + str_len + UI16_SZ;

	if (!MAKE_TBUF_SZ(entry_sz))
	    return 0;

#ifdef DEBUG
	startp = tracep;
#endif
	PUT_UI8(tracep, ERTS_MT_BLOCK_TYPE_HDR_TAG);
	PUT_UI16(tracep, entry_sz);
	PUT_UI16(tracep, nflags);
	PUT_UI16(tracep, (Uint16) i);
	PUT_UI8(tracep, (byte) str_len);
	sys_memcpy((void *) tracep, (void *) str, str_len);
	tracep += str_len;
	PUT_UI16(tracep, no);
	ASSERT(startp + entry_sz == tracep);
    }

    entry_sz = UI8_SZ + UI16_SZ;
    if (!MAKE_TBUF_SZ(entry_sz))
	return 0;
    PUT_UI8(tracep, ERTS_MT_END_OF_HDR_TAG);
    PUT_UI16(tracep, entry_sz);

    return 1;
}
Ejemplo n.º 11
0
static void ERTS_INLINE atom_init(Eterm *atom, char *name)
{
    *atom = am_atom_put(name, sys_strlen(name));
}
Ejemplo n.º 12
0
BIF_RETTYPE erts_internal_open_port_2(BIF_ALIST_2)
{
    BIF_RETTYPE ret;
    Port *port;
    Eterm res;
    char *str;
    int err_type, err_num;
    ErtsLinkData *ldp;
    ErtsLink *lnk;

    port = open_port(BIF_P, BIF_ARG_1, BIF_ARG_2, &err_type, &err_num);
    if (!port) {
	if (err_type == -3) {
	    ASSERT(err_num == BADARG || err_num == SYSTEM_LIMIT);
	    if (err_num == BADARG)
                res = am_badarg;
            else if (err_num == SYSTEM_LIMIT)
                res = am_system_limit;
            else
                /* this is only here to silence gcc, it should not happen */
                BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
	} else if (err_type == -2) {
	    str = erl_errno_id(err_num);
            res = erts_atom_put((byte *) str, sys_strlen(str), ERTS_ATOM_ENC_LATIN1, 1);
	} else {
	    res = am_einval;
	}
        BIF_RET(res);
    }

    ldp = erts_link_create(ERTS_LNK_TYPE_PORT, BIF_P->common.id, port->common.id);
    ASSERT(ldp->a.other.item == port->common.id);
    ASSERT(ldp->b.other.item == BIF_P->common.id);
    /*
     * This link should not already be present, but can potentially
     * due to id wrapping...
     */
    lnk = erts_link_tree_lookup_insert(&ERTS_P_LINKS(BIF_P), &ldp->a);
    erts_link_tree_insert(&ERTS_P_LINKS(port), &ldp->b);

    if (port->drv_ptr->flags & ERL_DRV_FLAG_USE_INIT_ACK) {

        /* Copied from erl_port_task.c */
        port->async_open_port = erts_alloc(ERTS_ALC_T_PRTSD,
                                           sizeof(*port->async_open_port));
        erts_make_ref_in_array(port->async_open_port->ref);
        port->async_open_port->to = BIF_P->common.id;

        /*
         * We unconditionaly *must* do a receive on a message
         * containing the reference after this...
         */
        ERTS_RECV_MARK_SAVE(BIF_P);
        ERTS_RECV_MARK_SET(BIF_P);

        res = erts_proc_store_ref(BIF_P, port->async_open_port->ref);
    } else {
        res = port->common.id;
    }

    if (IS_TRACED_FL(BIF_P, F_TRACE_PROCS))
        trace_proc(BIF_P, ERTS_PROC_LOCK_MAIN, BIF_P,
                   am_link, port->common.id);

    ERTS_BIF_PREP_RET(ret, res);

    erts_port_release(port);

    if (lnk)
        erts_link_release(lnk);

    return ret;
}
Ejemplo n.º 13
0
static int
open_port(Process* p, Eterm name, Eterm settings, int *err_nump)
{
#define OPEN_PORT_ERROR(VAL) do { port_num = (VAL); goto do_return; } while (0)
    int i, port_num;
    Eterm option;
    Uint arity;
    Eterm* tp;
    Uint* nargs;
    erts_driver_t* driver;
    char* name_buf = NULL;
    SysDriverOpts opts;
    int binary_io;
    int soft_eof;
    Sint linebuf;
    Eterm edir = NIL;
    byte dir[MAXPATHLEN];

    /* These are the defaults */
    opts.packet_bytes = 0;
    opts.use_stdio = 1;
    opts.redir_stderr = 0;
    opts.read_write = 0;
    opts.hide_window = 0;
    opts.wd = NULL;
    opts.envir = NULL;
    opts.exit_status = 0;
    opts.overlapped_io = 0; 
    opts.spawn_type = ERTS_SPAWN_ANY; 
    opts.argv = NULL;
    binary_io = 0;
    soft_eof = 0;
    linebuf = 0;

    *err_nump = 0;

    if (is_not_list(settings) && is_not_nil(settings)) {
	goto badarg;
    }
    /*
     * Parse the settings.
     */

    if (is_not_nil(settings)) {
	nargs = list_val(settings);
	while (1) {
	    if (is_tuple_arity(*nargs, 2)) {
		tp = tuple_val(*nargs);
		arity = *tp++;
		option = *tp++;
		if (option == am_packet) {
		    if (is_not_small(*tp)) {
			goto badarg;
		    }
		    opts.packet_bytes = signed_val(*tp);
		    switch (opts.packet_bytes) {
		    case 1:
		    case 2:
		    case 4:
			break;
		    default:
			goto badarg;
		   }
		} else if (option == am_line) {
		    if (is_not_small(*tp)) {
			goto badarg;
		    }
		    linebuf = signed_val(*tp);
		    if (linebuf <= 0) {
			goto badarg;
		    }
		} else if (option == am_env) {
		    byte* bytes;
		    if ((bytes = convert_environment(p, *tp)) == NULL) {
			goto badarg;
		    }
		    opts.envir = (char *) bytes;
		} else if (option == am_args) {
		    char **av;
		    char **oav = opts.argv;
		    if ((av = convert_args(*tp)) == NULL) {
			goto badarg;
		    }
		    opts.argv = av;
		    if (oav) {
			opts.argv[0] = oav[0];
			oav[0] = erts_default_arg0;
			free_args(oav);
		    }

		} else if (option == am_arg0) {
		    char *a0;

		    if ((a0 = erts_convert_filename_to_native(*tp, ERTS_ALC_T_TMP, 1)) == NULL) {
			goto badarg;
		    }
		    if (opts.argv == NULL) {
			opts.argv = erts_alloc(ERTS_ALC_T_TMP, 
					       2 * sizeof(char **));
			opts.argv[0] = a0;
			opts.argv[1] = NULL;
		    } else {
			if (opts.argv[0] != erts_default_arg0) {
			    erts_free(ERTS_ALC_T_TMP, opts.argv[0]);
			}
			opts.argv[0] = a0;
		    }
		} else if (option == am_cd) {
		    edir = *tp;
		} else {
		    goto badarg;
		}
	    } else if (*nargs == am_stream) {
		opts.packet_bytes = 0;
	    } else if (*nargs == am_use_stdio) {
		opts.use_stdio = 1;
	    } else if (*nargs == am_stderr_to_stdout) {
		opts.redir_stderr = 1;
	    } else if (*nargs == am_line) {
		linebuf = 512;
	    } else if (*nargs == am_nouse_stdio) {
		opts.use_stdio = 0;
	    } else if (*nargs == am_binary) {
		binary_io = 1;
	    } else if (*nargs == am_in) {
		opts.read_write |= DO_READ;
	    } else if (*nargs == am_out) {
		opts.read_write |= DO_WRITE;
	    } else if (*nargs == am_eof) {
		soft_eof = 1;
	    } else if (*nargs == am_hide) {
		opts.hide_window = 1;
	    } else if (*nargs == am_exit_status) {
		opts.exit_status = 1;
	    } else if (*nargs == am_overlapped_io) {
		opts.overlapped_io = 1;
	    } else {
		goto badarg;
	    }
	    if (is_nil(*++nargs)) 
		break;
	    if (is_not_list(*nargs)) {
		goto badarg;
	    }
	    nargs = list_val(*nargs);
	}
    }
    if (opts.read_write == 0)	/* implement default */
	opts.read_write = DO_READ|DO_WRITE;

    /* Mutually exclusive arguments. */
    if((linebuf && opts.packet_bytes) || 
       (opts.redir_stderr && !opts.use_stdio)) {
	goto badarg;
    }

    /*
     * Parse the first argument and start the appropriate driver.
     */
    
    if (is_atom(name) || (i = is_string(name))) {
	/* a vanilla port */
	if (is_atom(name)) {
	    name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
					   atom_tab(atom_val(name))->len+1);
	    sys_memcpy((void *) name_buf,
		       (void *) atom_tab(atom_val(name))->name, 
		       atom_tab(atom_val(name))->len);
	    name_buf[atom_tab(atom_val(name))->len] = '\0';
	} else {
	    name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
	    if (intlist_to_buf(name, name_buf, i) != i)
		erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
	    name_buf[i] = '\0';
	}
	driver = &vanilla_driver;
    } else {   
	if (is_not_tuple(name)) {
	    goto badarg;		/* Not a process or fd port */
	}
	tp = tuple_val(name);
	arity = *tp++;

	if (arity == make_arityval(0)) {
	    goto badarg;
	}
    
	if (*tp == am_spawn || *tp == am_spawn_driver) {	/* A process port */
	    if (arity != make_arityval(2)) {
		goto badarg;
	    }
	    name = tp[1];
	    if (is_atom(name)) {
		name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
					       atom_tab(atom_val(name))->len+1);
		sys_memcpy((void *) name_buf,
			   (void *) atom_tab(atom_val(name))->name, 
			   atom_tab(atom_val(name))->len);
		name_buf[atom_tab(atom_val(name))->len] = '\0';
	    } else if ((i = is_string(name))) {
		name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
		if (intlist_to_buf(name, name_buf, i) != i)
		    erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
		name_buf[i] = '\0';
	    } else {
		goto badarg;
	    }
	    if (*tp == am_spawn_driver) {
		opts.spawn_type = ERTS_SPAWN_DRIVER;
	    }
	    driver = &spawn_driver;
	} else if (*tp == am_spawn_executable) {	/* A program */
	    /*
	     * {spawn_executable,Progname}
	     */
	    
	    if (arity != make_arityval(2)) {
		goto badarg;
	    }
	    name = tp[1];
	    if ((name_buf = erts_convert_filename_to_native(name,ERTS_ALC_T_TMP,0)) == NULL) {
		goto badarg;
	    }
	    opts.spawn_type = ERTS_SPAWN_EXECUTABLE;
	    driver = &spawn_driver;
	} else if (*tp == am_fd) { /* An fd port */
	    int n;
	    struct Sint_buf sbuf;
	    char* p;

	    if (arity != make_arityval(3)) {
		goto badarg;
	    }
	    if (is_not_small(tp[1]) || is_not_small(tp[2])) {
		goto badarg;
	    }
	    opts.ifd = unsigned_val(tp[1]);
	    opts.ofd = unsigned_val(tp[2]);

	    /* Syntesize name from input and output descriptor. */
	    name_buf = erts_alloc(ERTS_ALC_T_TMP,
				  2*sizeof(struct Sint_buf) + 2); 
	    p = Sint_to_buf(opts.ifd, &sbuf);
	    n = sys_strlen(p);
	    sys_strncpy(name_buf, p, n);
	    name_buf[n] = '/';
	    p = Sint_to_buf(opts.ofd, &sbuf);
	    sys_strcpy(name_buf+n+1, p);

	    driver = &fd_driver;
	} else {
	    goto badarg;
	}
    }

    if ((driver != &spawn_driver && opts.argv != NULL) ||
	(driver == &spawn_driver && 
	 opts.spawn_type != ERTS_SPAWN_EXECUTABLE && 
	 opts.argv != NULL)) {
	/* Argument vector only if explicit spawn_executable */
	goto badarg;
    }

    if (edir != NIL) {
	/* A working directory is expressed differently if spawn_executable, i.e. Unicode is handles 
	   for spawn_executable... */
	if (opts.spawn_type != ERTS_SPAWN_EXECUTABLE) {
	    Eterm iolist;
	    DeclareTmpHeap(heap,4,p);
	    int r;
	    
	    UseTmpHeap(4,p);
	    heap[0] = edir;
	    heap[1] = make_list(heap+2);
	    heap[2] = make_small(0);
	    heap[3] = NIL;
	    iolist = make_list(heap);
	    r = io_list_to_buf(iolist, (char*) dir, MAXPATHLEN);
	    UnUseTmpHeap(4,p);
	    if (r < 0) {
		goto badarg;
	    }
	    opts.wd = (char *) dir;
	} else {
	    if ((opts.wd = erts_convert_filename_to_native(edir,ERTS_ALC_T_TMP,0)) == NULL) {
		goto badarg;
	    }
	}
    }

    if (driver != &spawn_driver && opts.exit_status) {
	goto badarg;
    }
    
    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
        trace_virtual_sched(p, am_out);
    }
    

    erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);

    port_num = erts_open_driver(driver, p->id, name_buf, &opts, err_nump);
#ifdef USE_VM_PROBES
    if (port_num >= 0 && DTRACE_ENABLED(port_open)) {
        DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE);
        DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);

        dtrace_proc_str(p, process_str);
        erts_snprintf(port_str, sizeof(port_str), "%T", erts_port[port_num].id);
        DTRACE3(port_open, process_str, name_buf, port_str);
    }
#endif
    erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);

    if (port_num < 0) {
	DEBUGF(("open_driver returned %d(%d)\n", port_num, *err_nump));
    	if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
            trace_virtual_sched(p, am_in);
    	}
	OPEN_PORT_ERROR(port_num);
    }
    
    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
        trace_virtual_sched(p, am_in);
    }

    if (binary_io) {
	erts_port_status_bor_set(&erts_port[port_num],
				 ERTS_PORT_SFLG_BINARY_IO);
    }
    if (soft_eof) {
	erts_port_status_bor_set(&erts_port[port_num],
				 ERTS_PORT_SFLG_SOFT_EOF);
    }
    if (linebuf && erts_port[port_num].linebuf == NULL){
	erts_port[port_num].linebuf = allocate_linebuf(linebuf); 
	erts_port_status_bor_set(&erts_port[port_num],
				 ERTS_PORT_SFLG_LINEBUF_IO);
    }
 
 do_return:
    if (name_buf)
	erts_free(ERTS_ALC_T_TMP, (void *) name_buf);
    if (opts.argv) {
	free_args(opts.argv);
    }
    if (opts.wd && opts.wd != ((char *)dir)) {
	erts_free(ERTS_ALC_T_TMP, (void *) opts.wd);
    }
    return port_num;
    
 badarg:
    *err_nump = BADARG;
    OPEN_PORT_ERROR(-3);
    goto do_return;
#undef OPEN_PORT_ERROR
}
Ejemplo n.º 14
0
/**
 * log_send
 *
 * @brief
 *    Entry point for all logging functions.
 *
 * @param[in]    name           Category name.
 * @param[in]    priority       Information priority.
 * @param[in]    file_name      Name of file where call is located.
 * @param[in]    line_no        Line in the file where call is located.
 * @param[in]    func_name      Function name where call is located.
 *
 * @retval zero - on success
 * @retval non-zero - on failure
 ***************************************************************************/
int log_send( const char* name, 
                      LOG_LEVEL priority,
                      const char* file_name,
                      const int line_no,
                      const char* func_name,
                      const char* format,
                      ...)
{
    OSH_ERROR status = OSH_ERR_NONE;
    char *buf = NULL;
    int buf_size = 256;
    BOOL cr = FALSE;

    /* Current state check */
    if ( !osh_config.active || 
        (osh_config.my_pe == INVALID_PE) || 
        (osh_config.exec_mode.log_pe_list == (unsigned long long)INVALID_PE) )
    {
         return status;
    }

    /* Logging on the defined PE only */
    if ( (!PE_LIST_CHECK(osh_config.my_pe, osh_config.exec_mode.log_pe_list)) )
    {
         return status;
    }

    if ( ((unsigned)osh_config.exec_mode.log_level < priority) && 
         ((unsigned)osh_config.exec_mode.out_level < priority))
    {
        return status;
    }

    buf = (char*)sys_malloc(buf_size);
    if (!buf)
    {
        status = OSH_ERR_NO_MEMORY;
    }

    {
        va_list va;
        int n = 0;

        while (status == OSH_ERR_NONE) 
        {
            va_start(va, format);
            n = vsnprintf(buf, buf_size, format, va);
            va_end(va);

            /* If that worked, return */
            if (n > -1 && n < buf_size)
            {
                break;
            }

            /* Else try again with more space. */
            if (n > -1)     /* ISO/IEC 9899:1999 */
                buf_size = n + 1;
            else            /* twice the old size */
                buf_size *= 2;

            sys_free(buf);
            buf = (char*)sys_malloc(buf_size);
            if (!buf)
            {
                status = OSH_ERR_NO_MEMORY;
            }
        }

        if (status == OSH_ERR_NONE)
        {
            /* get length of data */
            buf_size = (int)sys_strlen(buf);

            /* cut off ended '\n' */
            if ((buf_size > 0) && (buf[buf_size-1] == '\n'))
            {
                buf[buf_size-1] = '\0';
                buf_size--;
                cr = TRUE;
            }
        }
    }

    if ( status == OSH_ERR_NONE )
    {
        UNREFERENCED_PARAMETER(file_name);
        UNREFERENCED_PARAMETER(func_name);
        UNREFERENCED_PARAMETER(line_no);

        /* Output into display */
        if (osh_config.exec_mode.out_file && ((unsigned)osh_config.exec_mode.out_level >= priority))
        {
            if (name && !sys_strcmp(OSH_STD, name))
            {
                fprintf(osh_config.exec_mode.out_file, "%s%s", 
                    buf,
                    (cr ? "\n" : "")
                    );
            }
            else
            {
                fprintf(osh_config.exec_mode.out_file, "[%s] %s: #%02d %s%s", 
                    __log_priority2str(priority),
                    (name ? name : ""),
                    osh_config.my_pe,
                    buf,
                    (cr ? "\n" : "")
                    );
            }
            fflush(osh_config.exec_mode.out_file);
        }

        /* Output into log */
        if (osh_config.exec_mode.log_file && ((unsigned)osh_config.exec_mode.log_level >= priority))
        {
            fprintf(osh_config.exec_mode.log_file, "[%s] %s: #%02d %s%s", 
                __log_priority2str(priority),
                (name ? name : ""),
                osh_config.my_pe,
                buf,
                (cr ? "\n" : "")
                );
             fflush(osh_config.exec_mode.log_file);
       }
    }

    if (buf)
    {
        sys_free(buf);
    }

    return status;
}
Ejemplo n.º 15
0
static Port *
open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
{
    Sint i;
    Eterm option;
    Uint arity;
    Eterm* tp;
    Uint* nargs;
    erts_driver_t* driver;
    char* name_buf = NULL;
    SysDriverOpts opts;
    Sint linebuf;
    Eterm edir = NIL;
    byte dir[MAXPATHLEN];
    erts_aint32_t sflgs = 0;
    Port *port;

    /* These are the defaults */
    opts.packet_bytes = 0;
    opts.use_stdio = 1;
    opts.redir_stderr = 0;
    opts.read_write = 0;
    opts.hide_window = 0;
    opts.wd = NULL;
    opts.envir = NULL;
    opts.exit_status = 0;
    opts.overlapped_io = 0; 
    opts.spawn_type = ERTS_SPAWN_ANY; 
    opts.argv = NULL;
    opts.parallelism = erts_port_parallelism;
    linebuf = 0;

    *err_nump = 0;

    if (is_not_list(settings) && is_not_nil(settings)) {
	goto badarg;
    }
    /*
     * Parse the settings.
     */

    if (is_not_nil(settings)) {
	nargs = list_val(settings);
	while (1) {
	    if (is_tuple_arity(*nargs, 2)) {
		tp = tuple_val(*nargs);
		arity = *tp++;
		option = *tp++;
		if (option == am_packet) {
		    if (is_not_small(*tp)) {
			goto badarg;
		    }
		    opts.packet_bytes = signed_val(*tp);
		    switch (opts.packet_bytes) {
		    case 1:
		    case 2:
		    case 4:
			break;
		    default:
			goto badarg;
		   }
		} else if (option == am_line) {
		    if (is_not_small(*tp)) {
			goto badarg;
		    }
		    linebuf = signed_val(*tp);
		    if (linebuf <= 0) {
			goto badarg;
		    }
		} else if (option == am_env) {
		    byte* bytes;
		    if ((bytes = convert_environment(p, *tp)) == NULL) {
			goto badarg;
		    }
		    opts.envir = (char *) bytes;
		} else if (option == am_args) {
		    char **av;
		    char **oav = opts.argv;
		    if ((av = convert_args(*tp)) == NULL) {
			goto badarg;
		    }
		    opts.argv = av;
		    if (oav) {
			opts.argv[0] = oav[0];
			oav[0] = erts_default_arg0;
			free_args(oav);
		    }

		} else if (option == am_arg0) {
		    char *a0;

		    if ((a0 = erts_convert_filename_to_native(*tp, NULL, 0, ERTS_ALC_T_TMP, 1, 1, NULL)) == NULL) {
			goto badarg;
		    }
		    if (opts.argv == NULL) {
			opts.argv = erts_alloc(ERTS_ALC_T_TMP, 
					       2 * sizeof(char **));
			opts.argv[0] = a0;
			opts.argv[1] = NULL;
		    } else {
			if (opts.argv[0] != erts_default_arg0) {
			    erts_free(ERTS_ALC_T_TMP, opts.argv[0]);
			}
			opts.argv[0] = a0;
		    }
		} else if (option == am_cd) {
		    edir = *tp;
		} else if (option == am_parallelism) {
		    if (*tp == am_true)
			opts.parallelism = 1;
		    else if (*tp == am_false)
			opts.parallelism = 0;
		    else
			goto badarg;
		} else {
		    goto badarg;
		}
	    } else if (*nargs == am_stream) {
		opts.packet_bytes = 0;
	    } else if (*nargs == am_use_stdio) {
		opts.use_stdio = 1;
	    } else if (*nargs == am_stderr_to_stdout) {
		opts.redir_stderr = 1;
	    } else if (*nargs == am_line) {
		linebuf = 512;
	    } else if (*nargs == am_nouse_stdio) {
		opts.use_stdio = 0;
	    } else if (*nargs == am_binary) {
		sflgs |= ERTS_PORT_SFLG_BINARY_IO;
	    } else if (*nargs == am_in) {
		opts.read_write |= DO_READ;
	    } else if (*nargs == am_out) {
		opts.read_write |= DO_WRITE;
	    } else if (*nargs == am_eof) {
		sflgs |= ERTS_PORT_SFLG_SOFT_EOF;
	    } else if (*nargs == am_hide) {
		opts.hide_window = 1;
	    } else if (*nargs == am_exit_status) {
		opts.exit_status = 1;
	    } else if (*nargs == am_overlapped_io) {
		opts.overlapped_io = 1;
	    } else {
		goto badarg;
	    }
	    if (is_nil(*++nargs)) 
		break;
	    if (is_not_list(*nargs)) {
		goto badarg;
	    }
	    nargs = list_val(*nargs);
	}
    }
    if (opts.read_write == 0)	/* implement default */
	opts.read_write = DO_READ|DO_WRITE;

    /* Mutually exclusive arguments. */
    if((linebuf && opts.packet_bytes) || 
       (opts.redir_stderr && !opts.use_stdio)) {
	goto badarg;
    }

    /*
     * Parse the first argument and start the appropriate driver.
     */
    
    if (is_atom(name) || (i = is_string(name))) {
	/* a vanilla port */
	if (is_atom(name)) {
	    name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
					   atom_tab(atom_val(name))->len+1);
	    sys_memcpy((void *) name_buf,
		       (void *) atom_tab(atom_val(name))->name, 
		       atom_tab(atom_val(name))->len);
	    name_buf[atom_tab(atom_val(name))->len] = '\0';
	} else {
	    name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
	    if (intlist_to_buf(name, name_buf, i) != i)
		erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error\n", __FILE__, __LINE__);
	    name_buf[i] = '\0';
	}
	driver = &vanilla_driver;
    } else {   
	if (is_not_tuple(name)) {
	    goto badarg;		/* Not a process or fd port */
	}
	tp = tuple_val(name);
	arity = *tp++;

	if (arity == make_arityval(0)) {
	    goto badarg;
	}
    
	if (*tp == am_spawn || *tp == am_spawn_driver || *tp == am_spawn_executable) {	/* A process port */
	    int encoding;
	    if (arity != make_arityval(2)) {
		goto badarg;
	    }
	    name = tp[1];
	    encoding = erts_get_native_filename_encoding();
	    /* Do not convert the command to utf-16le yet, do that in win32 specific code */
	    /* since the cmd is used for comparsion with drivers names and copied to port info */
	    if (encoding == ERL_FILENAME_WIN_WCHAR) {
		encoding = ERL_FILENAME_UTF8;
	    }
	    if ((name_buf = erts_convert_filename_to_encoding(name, NULL, 0, ERTS_ALC_T_TMP,0,1, encoding, NULL, 0))
		== NULL) {
		goto badarg;
	    }

	    if (*tp == am_spawn_driver) {
		opts.spawn_type = ERTS_SPAWN_DRIVER;
	    } else if (*tp == am_spawn_executable) {
		opts.spawn_type = ERTS_SPAWN_EXECUTABLE;
	    }

	    driver = &spawn_driver;
	} else if (*tp == am_fd) { /* An fd port */
	    int n;
	    struct Sint_buf sbuf;
	    char* p;

	    if (arity != make_arityval(3)) {
		goto badarg;
	    }
	    if (is_not_small(tp[1]) || is_not_small(tp[2])) {
		goto badarg;
	    }
	    opts.ifd = unsigned_val(tp[1]);
	    opts.ofd = unsigned_val(tp[2]);

	    /* Syntesize name from input and output descriptor. */
	    name_buf = erts_alloc(ERTS_ALC_T_TMP,
				  2*sizeof(struct Sint_buf) + 2); 
	    p = Sint_to_buf(opts.ifd, &sbuf);
	    n = sys_strlen(p);
	    sys_strncpy(name_buf, p, n);
	    name_buf[n] = '/';
	    p = Sint_to_buf(opts.ofd, &sbuf);
	    sys_strcpy(name_buf+n+1, p);

	    driver = &fd_driver;
	} else {
	    goto badarg;
	}
    }

    if ((driver != &spawn_driver && opts.argv != NULL) ||
	(driver == &spawn_driver && 
	 opts.spawn_type != ERTS_SPAWN_EXECUTABLE && 
	 opts.argv != NULL)) {
	/* Argument vector only if explicit spawn_executable */
	goto badarg;
    }

    if (edir != NIL) {
	if ((opts.wd = erts_convert_filename_to_native(edir, NULL, 0, ERTS_ALC_T_TMP,0,1,NULL)) == NULL) {
	    goto badarg;
	}
    }

    if (driver != &spawn_driver && opts.exit_status) {
	goto badarg;
    }
    
    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
        trace_sched(p, ERTS_PROC_LOCK_MAIN, am_out);
    }
    

    erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);

    port = erts_open_driver(driver, p->common.id, name_buf, &opts, err_typep, err_nump);
#ifdef USE_VM_PROBES
    if (port && DTRACE_ENABLED(port_open)) {
        DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE);
        DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);

        dtrace_proc_str(p, process_str);
        erts_snprintf(port_str, sizeof(DTRACE_CHARBUF_NAME(port_str)), "%T", port->common.id);
        DTRACE3(port_open, process_str, name_buf, port_str);
    }
#endif

    if (port && IS_TRACED_FL(port, F_TRACE_PORTS))
        trace_port(port, am_getting_linked, p->common.id);

    erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);

    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
        trace_sched(p, ERTS_PROC_LOCK_MAIN, am_in);
    }

    if (!port) {
	DEBUGF(("open_driver returned (%d:%d)\n",
		err_typep ? *err_typep : 4711,
		err_nump ? *err_nump : 4711));
	goto do_return;
    }

    if (linebuf && port->linebuf == NULL){
	port->linebuf = allocate_linebuf(linebuf);
	sflgs |= ERTS_PORT_SFLG_LINEBUF_IO;
    }

    if (sflgs)
	erts_atomic32_read_bor_relb(&port->state, sflgs);
 
 do_return:
    if (name_buf)
	erts_free(ERTS_ALC_T_TMP, (void *) name_buf);
    if (opts.argv) {
	free_args(opts.argv);
    }
    if (opts.wd && opts.wd != ((char *)dir)) {
	erts_free(ERTS_ALC_T_TMP, (void *) opts.wd);
    }
    return port;
    
 badarg:
    if (err_typep)
	*err_typep = -3;
    if (err_nump)
	*err_nump = BADARG;
    port = NULL;
    goto do_return;
}
Ejemplo n.º 16
0
static int do_load_driver_entry(DE_Handle *dh, char *path, char *name)
{
    void *init_handle;
    int res;
    ErlDrvEntry *dp;

    assert_drv_list_rwlocked();

    if ((res =  erts_sys_ddll_open(path, &(dh->handle), NULL)) != ERL_DE_NO_ERROR) {
	return res;
    }
    
    if ((res = erts_sys_ddll_load_driver_init(dh->handle, 
					      &init_handle)) != ERL_DE_NO_ERROR) {
	res = ERL_DE_LOAD_ERROR_NO_INIT;
	goto error;
    }
    
    dp = erts_sys_ddll_call_init(init_handle);
    if (dp == NULL) {
	res = ERL_DE_LOAD_ERROR_FAILED_INIT;
	goto error;
    }

    switch (dp->extended_marker) {
    case ERL_DRV_EXTENDED_MARKER:
	if (dp->major_version < ERL_DRV_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD
	    || (ERL_DRV_EXTENDED_MAJOR_VERSION < dp->major_version
		|| (ERL_DRV_EXTENDED_MAJOR_VERSION == dp->major_version
		    && ERL_DRV_EXTENDED_MINOR_VERSION < dp->minor_version))) {
	    /* Incompatible driver version */
	    res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
	    goto error;
	}
	break;
    default:
	/* Old driver; needs to be recompiled... */
	res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
	goto error;
    }

    if (strcmp(name, dp->driver_name) != 0) {
	res = ERL_DE_LOAD_ERROR_BAD_NAME;
	goto error;
    }
    erts_atomic_init_nob(&(dh->refc), (erts_aint_t) 0);
    erts_atomic32_init_nob(&dh->port_count, 0);
    dh->full_path = erts_alloc(ERTS_ALC_T_DDLL_HANDLE, sys_strlen(path) + 1);
    sys_strcpy(dh->full_path, path);
    dh->flags = 0;
    dh->status = ERL_DE_OK;

    if (erts_add_driver_entry(dp, dh, 1) != 0 /* io.c */) { 
	/*
	 * The init in the driver struct did not return 0 
	 */
	erts_free(ERTS_ALC_T_DDLL_HANDLE, dh->full_path);
	dh->full_path = NULL;
	res = ERL_DE_LOAD_ERROR_FAILED_INIT;
	goto error;
    }
    return ERL_DE_NO_ERROR;

error:
    erts_sys_ddll_close(dh->handle);
    return res;
}
Ejemplo n.º 17
0
static int
print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr)
{
    int i;
    BeamInstr tag;
    char* sign;
    char* start_prog;		/* Start of program for packer. */
    char* prog;			/* Current position in packer program. */
    BeamInstr stack[8];		/* Stack for packer. */
    BeamInstr* sp = stack;		/* Points to next free position. */
    BeamInstr packed = 0;		/* Accumulator for packed operations. */
    BeamInstr args[8];		/* Arguments for this instruction. */
    BeamInstr* ap;			/* Pointer to arguments. */
    BeamInstr* unpacked;		/* Unpacked arguments */
    BeamInstr* first_arg;               /* First argument */

    start_prog = opc[op].pack;

    if (start_prog[0] == '\0') {
	/*
	 * There is no pack program.
	 * Avoid copying because instructions containing bignum operands
	 * are bigger than actually declared.
	 */
        addr++;
        ap = addr;
    } else {
#if defined(ARCH_64) && defined(CODE_MODEL_SMALL)
        BeamInstr instr_word = addr[0];
#endif
        addr++;

	/*
	 * Copy all arguments to a local buffer for the unpacking.
	 */

	ASSERT(size <= sizeof(args)/sizeof(args[0]));
	ap = args;
	for (i = 0; i < size; i++) {
	    *ap++ = addr[i];
	}

	/*
	 * Undo any packing done by the loader.  This is easily done by running
	 * the packing program backwards and in reverse.
	 */

	prog = start_prog + sys_strlen(start_prog);
	while (start_prog < prog) {
	    prog--;
	    switch (*prog) {
	    case 'f':
	    case 'g':
	    case 'q':
		*ap++ = *--sp;
		break;
#ifdef ARCH_64
	    case '1':		/* Tightest shift */
		*ap++ = (packed & BEAM_TIGHTEST_MASK) << 3;
		packed >>= BEAM_TIGHTEST_SHIFT;
		break;
#endif
	    case '2':		/* Tight shift */
		*ap++ = packed & BEAM_TIGHT_MASK;
		packed >>= BEAM_TIGHT_SHIFT;
		break;
	    case '3':		/* Loose shift */
		*ap++ = packed & BEAM_LOOSE_MASK;
		packed >>= BEAM_LOOSE_SHIFT;
		break;
#ifdef ARCH_64
	    case '4':		/* Shift 32 steps */
		*ap++ = packed & BEAM_WIDE_MASK;
		packed >>= BEAM_WIDE_SHIFT;
		break;
#endif
	    case 'p':
		*sp++ = *--ap;
		break;
	    case 'P':
		packed = *--sp;
		break;
#if defined(ARCH_64) && defined(CODE_MODEL_SMALL)
            case '#':       /* -1 */
            case '$':       /* -2 */
            case '%':       /* -3 */
            case '&':       /* -4 */
            case '\'':      /* -5 */
            case '(':       /* -6 */
                packed = (packed << BEAM_WIDE_SHIFT) | BeamExtraData(instr_word);
		break;
#endif
	    default:
                erts_exit(ERTS_ERROR_EXIT, "beam_debug: invalid packing op: %c\n", *prog);
	    }
	}
	ap = args;
    }

    first_arg = ap;

    /*
     * Print the name and all operands of the instructions.
     */
	
    erts_print(to, to_arg, "%s ", opc[op].name);
    sign = opc[op].sign;
    while (*sign) {
	switch (*sign) {
	case 'r':		/* x(0) */
	    erts_print(to, to_arg, "r(0)");
	    break;
	case 'x':		/* x(N) */
	    {
		Uint n = ap[0] / sizeof(Eterm);
		erts_print(to, to_arg, "x(%d)", n);
		ap++;
	    }
	    break;
	case 'y':		/* y(N) */
	    {
		Uint n = ap[0] / sizeof(Eterm) - CP_SIZE;
		erts_print(to, to_arg, "y(%d)", n);
		ap++;
	    }
	    break;
	case 'n':		/* Nil */
	    erts_print(to, to_arg, "[]");
	    break;
        case 'S':               /* Register */
            {
                Uint reg_type = (*ap & 1) ? 'y' : 'x';
                Uint n = ap[0] / sizeof(Eterm);
                erts_print(to, to_arg, "%c(%d)", reg_type, n);
		ap++;
                break;
            }
	case 's':		/* Any source (tagged constant or register) */
	    tag = loader_tag(*ap);
	    if (tag == LOADER_X_REG) {
		erts_print(to, to_arg, "x(%d)", loader_x_reg_index(*ap));
		ap++;
		break;
	    } else if (tag == LOADER_Y_REG) {
		erts_print(to, to_arg, "y(%d)", loader_y_reg_index(*ap) - CP_SIZE);
		ap++;
		break;
	    }
	    /*FALLTHROUGH*/
	case 'a':		/* Tagged atom */
	case 'i':		/* Tagged integer */
	case 'c':		/* Tagged constant */
	case 'q':		/* Tagged literal */
	    erts_print(to, to_arg, "%T", (Eterm) *ap);
	    ap++;
	    break;
	case 'A':
	    erts_print(to, to_arg, "%d", arityval( (Eterm) ap[0]));
	    ap++;
	    break;
	case 'd':		/* Destination (x(0), x(N), y(N)) */
	    if (*ap & 1) {
		erts_print(to, to_arg, "y(%d)",
			   *ap / sizeof(Eterm) - CP_SIZE);
	    } else {
		erts_print(to, to_arg, "x(%d)",
			   *ap / sizeof(Eterm));
	    }
	    ap++;
	    break;
	case 't':               /* Untagged integers */
	case 'I':
        case 'W':
	    switch (op) {
	    case op_i_gc_bif1_jWstd:
	    case op_i_gc_bif2_jWtssd:
	    case op_i_gc_bif3_jWtssd:
		{
		    const ErtsGcBif* p;
		    BifFunction gcf = (BifFunction) *ap;
		    for (p = erts_gc_bifs; p->bif != 0; p++) {
			if (p->gc_bif == gcf) {
			    print_bif_name(to, to_arg, p->bif);
			    break;
			}
		    }
		    if (p->bif == 0) {
			erts_print(to, to_arg, "%d", (Uint)gcf);
		    }
		    break;
		}
	    case op_i_make_fun_Wt:
                if (*sign == 'W') {
                    ErlFunEntry* fe = (ErlFunEntry *) *ap;
                    ErtsCodeMFA* cmfa = find_function_from_pc(fe->address);
		    erts_print(to, to_arg, "%T:%T/%bpu", cmfa->module,
                               cmfa->function, cmfa->arity);
                } else {
                    erts_print(to, to_arg, "%d", *ap);
                }
                break;
	    case op_i_bs_match_string_xfWW:
                if (ap - first_arg < 3) {
                    erts_print(to, to_arg, "%d", *ap);
                } else {
                    Uint bits = ap[-1];
                    Uint bytes = (bits+7)/8;
                    byte* str = (byte *) *ap;
                    print_byte_string(to, to_arg, str, bytes);
                }
                break;
	    case op_bs_put_string_WW:
                if (ap - first_arg == 0) {
                    erts_print(to, to_arg, "%d", *ap);
                } else {
                    Uint bytes = ap[-1];
                    byte* str = (byte *) ap[0];
                    print_byte_string(to, to_arg, str, bytes);
                }
                break;
	    default:
		erts_print(to, to_arg, "%d", *ap);
	    }
	    ap++;
	    break;
	case 'f':		/* Destination label */
            switch (op) {
            case op_catch_yf:
                erts_print(to, to_arg, "f(" HEXF ")", catch_pc((BeamInstr)*ap));
                break;
            default:
                {
                    BeamInstr* target = f_to_addr(addr, op, ap);
                    ErtsCodeMFA* cmfa = find_function_from_pc(target);
                    if (!cmfa || erts_codemfa_to_code(cmfa) != target) {
                        erts_print(to, to_arg, "f(" HEXF ")", target);
                    } else {
                        erts_print(to, to_arg, "%T:%T/%bpu", cmfa->module,
                                   cmfa->function, cmfa->arity);
                    }
                    ap++;
                }
                break;
            }
            break;
	case 'p':		/* Pointer (to label) */
	    {
                BeamInstr* target = f_to_addr(addr, op, ap);
                erts_print(to, to_arg, "p(" HEXF ")", target);
		ap++;
	    }
	    break;
	case 'j':		/* Pointer (to label) */
            if (*ap == 0) {
                erts_print(to, to_arg, "j(0)");
            } else {
                BeamInstr* target = f_to_addr(addr, op, ap);
                erts_print(to, to_arg, "j(" HEXF ")", target);
            }
	    ap++;
	    break;
	case 'e':		/* Export entry */
	    {
		Export* ex = (Export *) *ap;
		erts_print(to, to_arg,
			   "%T:%T/%bpu", (Eterm) ex->info.mfa.module,
                           (Eterm) ex->info.mfa.function,
                           ex->info.mfa.arity);
		ap++;
	    }
	    break;
	case 'F':		/* Function definition */
	    break;
	case 'b':
	    print_bif_name(to, to_arg, (BifFunction) *ap);
	    ap++;
	    break;
	case 'P':	/* Byte offset into tuple (see beam_load.c) */
	case 'Q':	/* Like 'P', but packable */
	    erts_print(to, to_arg, "%d", (*ap / sizeof(Eterm)) - 1);
	    ap++;
	    break;
	case 'l':		/* fr(N) */
	    erts_print(to, to_arg, "fr(%d)", loader_reg_index(ap[0]));
	    ap++;
	    break;
	default:
	    erts_print(to, to_arg, "???");
	    ap++;
	    break;
	}
	erts_print(to, to_arg, " ");
	sign++;
    }

    /*
     * Print more information about certain instructions.
     */

    unpacked = ap;
    ap = addr + size;

    /*
     * In the code below, never use ap[-1], ap[-2], ...
     * (will not work if the arguments have been packed).
     *
     * Instead use unpacked[-1], unpacked[-2], ...
     */
    switch (op) {
    case op_i_select_val_lins_xfI:
    case op_i_select_val_lins_yfI:
    case op_i_select_val_bins_xfI:
    case op_i_select_val_bins_yfI:
	{
	    int n = unpacked[-1];
	    int ix = n;
            Sint32* jump_tab = (Sint32 *)(ap + n);

	    while (ix--) {
		erts_print(to, to_arg, "%T ", (Eterm) ap[0]);
		ap++;
		size++;
	    }
	    ix = n;
	    while (ix--) {
                BeamInstr* target = f_to_addr_packed(addr, op, jump_tab);
		erts_print(to, to_arg, "f(" HEXF ") ", target);
                jump_tab++;
	    }
            size += (n+1) / 2;
	}
	break;
    case op_i_select_tuple_arity_xfI:
    case op_i_select_tuple_arity_yfI:
        {
            int n = unpacked[-1];
            int ix = n - 1; /* without sentinel */
            Sint32* jump_tab = (Sint32 *)(ap + n);

            while (ix--) {
                Uint arity = arityval(ap[0]);
                erts_print(to, to_arg, "{%d} ", arity, ap[1]);
                ap++;
                size++;
            }
            /* print sentinel */
            erts_print(to, to_arg, "{%T} ", ap[0], ap[1]);
            ap++;
            size++;
            ix = n;
            while (ix--) {
                BeamInstr* target = f_to_addr_packed(addr, op, jump_tab);
                erts_print(to, to_arg, "f(" HEXF ") ", target);
                jump_tab++;
            }
            size += (n+1) / 2;
        }
        break;
    case op_i_select_val2_xfcc:
    case op_i_select_val2_yfcc:
    case op_i_select_tuple_arity2_xfAA:
    case op_i_select_tuple_arity2_yfAA:
        {
            Sint32* jump_tab = (Sint32 *) ap;
            BeamInstr* target;
            int i;

            for (i = 0; i < 2; i++) {
                target = f_to_addr_packed(addr, op, jump_tab++);
                erts_print(to, to_arg, "f(" HEXF ") ", target);
            }
            size += 1;
        }
        break;
    case op_i_jump_on_val_xfIW:
    case op_i_jump_on_val_yfIW:
	{
	    int n = unpacked[-2];
            Sint32* jump_tab = (Sint32 *) ap;

            size += (n+1) / 2;
            while (n-- > 0) {
                BeamInstr* target = f_to_addr_packed(addr, op, jump_tab);
		erts_print(to, to_arg, "f(" HEXF ") ", target);
                jump_tab++;
	    }
	}
	break;
    case op_i_jump_on_val_zero_xfI:
    case op_i_jump_on_val_zero_yfI:
	{
	    int n = unpacked[-1];
            Sint32* jump_tab = (Sint32 *) ap;

            size += (n+1) / 2;
            while (n-- > 0) {
                BeamInstr* target = f_to_addr_packed(addr, op, jump_tab);
		erts_print(to, to_arg, "f(" HEXF ") ", target);
                jump_tab++;
	    }
	}
	break;
    case op_i_put_tuple_xI:
    case op_i_put_tuple_yI:
    case op_new_map_dtI:
    case op_update_map_assoc_sdtI:
    case op_update_map_exact_jsdtI:
	{
	    int n = unpacked[-1];

	    while (n > 0) {
		switch (loader_tag(ap[0])) {
		case LOADER_X_REG:
		    erts_print(to, to_arg, " x(%d)", loader_x_reg_index(ap[0]));
		    break;
		case LOADER_Y_REG:
		    erts_print(to, to_arg, " y(%d)", loader_y_reg_index(ap[0]) - CP_SIZE);
		    break;
		default:
		    erts_print(to, to_arg, " %T", (Eterm) ap[0]);
		    break;
		}
		ap++, size++, n--;
	    }
	}
	break;
    case op_i_new_small_map_lit_dtq:
        {
            Eterm *tp = tuple_val(unpacked[-1]);
            int n = arityval(*tp);

            while (n > 0) {
                switch (loader_tag(ap[0])) {
                case LOADER_X_REG:
                    erts_print(to, to_arg, " x(%d)", loader_x_reg_index(ap[0]));
                    break;
                case LOADER_Y_REG:
		    erts_print(to, to_arg, " y(%d)", loader_y_reg_index(ap[0]) - CP_SIZE);
		    break;
                default:
		    erts_print(to, to_arg, " %T", (Eterm) ap[0]);
		    break;
                }
                ap++, size++, n--;
            }
        }
        break;
    case op_i_get_map_elements_fsI:
	{
	    int n = unpacked[-1];

	    while (n > 0) {
		if (n % 3 == 1) {
		    erts_print(to, to_arg, " %X", ap[0]);
		} else {
		    switch (loader_tag(ap[0])) {
		    case LOADER_X_REG:
			erts_print(to, to_arg, " x(%d)", loader_x_reg_index(ap[0]));
			break;
		    case LOADER_Y_REG:
			erts_print(to, to_arg, " y(%d)", loader_y_reg_index(ap[0]) - CP_SIZE);
			break;
		    default:
			erts_print(to, to_arg, " %T", (Eterm) ap[0]);
			break;
		    }
		}
		ap++, size++, n--;
	    }
	}
	break;
    }
    erts_print(to, to_arg, "\n");

    return size;
}
Ejemplo n.º 18
0
/*
 * Backend for erl_ddll:format_error, handles all "soft" errors returned by builtins,
 * possibly by calling the system specific error handler
 */
BIF_RETTYPE erl_ddll_format_error_int_1(BIF_ALIST_1)
{
    Process *p = BIF_P;
    Eterm code_term = BIF_ARG_1;
    char *errstring = NULL;
    int errint;
    int len;
    Eterm ret = NIL;
    Eterm *hp;

    /* These errors can only appear in the erlang interface, not in the interface provided
       to drivers... */
    switch (code_term) {
    case am_inconsistent:
	errstring = "Driver name and/or driver options are inconsistent with "
	    "currently loaded driver";
	break;
    case am_linked_in_driver:
	errstring = "Driver is statically linked and "
	    "cannot be loaded/unloaded";
	break;
    case am_permanent:
	errstring = "DDLL driver is permanent an can not be unloaded/loaded";
	break;
    case am_not_loaded:
	errstring = "DDLL driver is not loaded";
	break;
    case am_not_loaded_by_this_process:
	errstring = "DDLL driver was not loaded by this process";
	break;
    case am_not_pending:
	errstring = "DDLL load not pending for this driver name";
	break;
    case am_already_loaded:
	errstring = "DDLL driver is already loaded successfully";
	break;
    case am_pending_reload:
	errstring = "Driver reloading is already pending";
	break;
    case am_pending_process:
	errstring = "Driver is loaded by others when attempting "
	    "option {reload, pending_driver}";
	break;
    default:
	/* A "real" error, we translate the atom to a code and translate the code 
	   to a string in the same manner as in the interface provided to drivers... */
	if (errdesc_to_code(code_term,&errint) != 0) {
	    goto error;
	}
	lock_drv_list();
	errstring = erts_ddll_error(errint);
	unlock_drv_list();
	break;
    }
    if (errstring == NULL) {
	goto error;
    }
    len = sys_strlen(errstring);
    hp = HAlloc(p, 2 * len);
    ret = buf_to_intlist(&hp, errstring, len, NIL);
    BIF_RET(ret);
 error:
    BIF_ERROR(p,BADARG);
} 
Ejemplo n.º 19
0
/**
 * sys_strdup
 *
 * @brief
 *    This function returns a newly allocated copy of string.
 *
 * @param[in]    string         This is a pointer to the original string.
 *
 * @retval pointer to new string - on success
 * @retval NULL - on failure
 ***************************************************************************/
char *sys_strdup(const char *string)
{
	return string ?
		sys_strcpy((char *)sys_malloc(sys_strlen(string) + 1), string) :
		NULL;
}