From 28544d5e6ecdc93a54a030766076be51a2dd5fbe Mon Sep 17 00:00:00 2001 From: SisMaker <1713699517@qq.com> Date: Sat, 29 May 2021 16:50:43 +0800 Subject: [PATCH] =?UTF-8?q?ft:=20=E4=BB=A3=E7=A0=81=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- c_src/tracer/nif_helpers.c | 195 -------------------- c_src/tracer/nif_helpers.h | 139 -------------- c_src/tracer/{lg_tracer.c => tpTracerNif.c} | 72 +++----- 3 files changed, 21 insertions(+), 385 deletions(-) delete mode 100644 c_src/tracer/nif_helpers.c delete mode 100644 c_src/tracer/nif_helpers.h rename c_src/tracer/{lg_tracer.c => tpTracerNif.c} (79%) diff --git a/c_src/tracer/nif_helpers.c b/c_src/tracer/nif_helpers.c deleted file mode 100644 index f29d76d..0000000 --- a/c_src/tracer/nif_helpers.c +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) 2014-2015, Loïc Hoguin -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -#include "nif_helpers.h" -#include -#include - -extern ERL_NIF_TERM atom_ok; -extern ERL_NIF_TERM atom__nif_thread_ret_; - -typedef struct nif_thread_message { - TAILQ_ENTRY(nif_thread_message) next_entry; - - ErlNifPid* from_pid; - void* function; - nif_thread_arg* args; -} nif_thread_message; - -typedef TAILQ_HEAD(nif_thread_mailbox, nif_thread_message) nif_thread_mailbox; - -typedef struct { - ErlNifTid tid; - ErlNifMutex* lock; - ErlNifCond* cond; - nif_thread_mailbox* mailbox; -} nif_thread_state; - -// Message. - -static nif_thread_message* nif_thread_message_alloc(void* f, nif_thread_arg* args, ErlNifPid* pid) -{ - nif_thread_message* msg = (nif_thread_message*)enif_alloc(sizeof(nif_thread_message)); - - msg->from_pid = pid; - msg->function = f; - msg->args = args; - - return msg; -} - -static void nif_thread_message_free(nif_thread_message* msg) -{ - enif_free(msg->from_pid); - enif_free(msg->args); - enif_free(msg); -} - -// Calls and casts. - -static ERL_NIF_TERM nif_thread_send(nif_thread_state* st, nif_thread_message* msg) -{ - enif_mutex_lock(st->lock); - - TAILQ_INSERT_TAIL(st->mailbox, msg, next_entry); - - enif_cond_signal(st->cond); - enif_mutex_unlock(st->lock); - - return atom_ok; -} - -ERL_NIF_TERM nif_thread_cast(ErlNifEnv* env, void (*f)(nif_thread_arg*), int a, ...) -{ - va_list ap; - int i; - - nif_thread_arg* args = (nif_thread_arg*)enif_alloc(a * sizeof(nif_thread_arg)); - - va_start(ap, a); - for (i = 0; i < a; i++) - args[i] = va_arg(ap, void*); - va_end(ap); - - nif_thread_message* msg = nif_thread_message_alloc(f, args, NULL); - - return nif_thread_send((nif_thread_state*)enif_priv_data(env), msg); -} - -ERL_NIF_TERM nif_thread_call(ErlNifEnv* env, ERL_NIF_TERM (*f)(ErlNifEnv*, nif_thread_arg*), int a, ...) -{ - va_list ap; - int i; - - nif_thread_arg* args = (nif_thread_arg*)enif_alloc(a * sizeof(nif_thread_arg)); - - va_start(ap, a); - for (i = 0; i < a; i++) - args[i] = va_arg(ap, void*); - va_end(ap); - - ErlNifPid* pid = (ErlNifPid*)enif_alloc(sizeof(ErlNifPid)); - nif_thread_message* msg = nif_thread_message_alloc((void*)f, args, enif_self(env, pid)); - - return nif_thread_send((nif_thread_state*)enif_priv_data(env), msg); -} - -// Main thread loop. - -static int nif_thread_receive(nif_thread_state* st, nif_thread_message** msg) -{ - enif_mutex_lock(st->lock); - - while (TAILQ_EMPTY(st->mailbox)) - enif_cond_wait(st->cond, st->lock); - - *msg = TAILQ_FIRST(st->mailbox); - TAILQ_REMOVE(st->mailbox, TAILQ_FIRST(st->mailbox), next_entry); - - enif_mutex_unlock(st->lock); - - if ((*msg)->function == NULL) - return 0; - - return 1; -} - -static void nif_thread_handle(ErlNifEnv* env, nif_thread_state* st, nif_thread_message* msg) -{ - if (msg->from_pid == NULL) { - void (*cast)(nif_thread_arg*) = msg->function; - cast(msg->args); - } else { - ERL_NIF_TERM (*call)(ErlNifEnv*, nif_thread_arg*) = msg->function; - ERL_NIF_TERM ret = call(env, msg->args); - - enif_send(NULL, msg->from_pid, env, - enif_make_tuple2(env, atom__nif_thread_ret_, ret)); - - enif_clear_env(env); - } - - nif_thread_message_free(msg); -} - -static void* nif_main_thread(void* obj) -{ - ErlNifEnv* env = enif_alloc_env(); - nif_thread_state* st = (nif_thread_state*)obj; - nif_thread_message* msg; - - while (nif_thread_receive(st, &msg)) - nif_thread_handle(env, st, msg); - - enif_free_env(env); - - return NULL; -} - -// Main thread creation/destruction. - -void* nif_create_main_thread(char* name) -{ - nif_thread_state* st = (nif_thread_state*)enif_alloc(sizeof(nif_thread_state)); - - st->lock = enif_mutex_create("nif_thread_mailbox_lock"); - st->cond = enif_cond_create("nif_thread_mailbox_cond"); - st->mailbox = (nif_thread_mailbox*)enif_alloc(sizeof(nif_thread_mailbox)); - TAILQ_INIT(st->mailbox); - -#if defined(__APPLE__) && defined(__MACH__) - // On OSX we identify ourselves as the main thread to ensure that - // we are compatible with libraries that require it. For example - // this is necessary with SDL2 in order to receive input events. - erl_drv_steal_main_thread(name, &(st->tid), nif_main_thread, st, NULL); -#else - enif_thread_create(name, &(st->tid), nif_main_thread, st, NULL); -#endif - - return (void*)st; -} - -void nif_destroy_main_thread(void* void_st) -{ - nif_thread_state* st = (nif_thread_state*)void_st; - nif_thread_message* msg = nif_thread_message_alloc(NULL, NULL, NULL); - - nif_thread_send(st, msg); - enif_thread_join(st->tid, NULL); - - enif_cond_destroy(st->cond); - enif_mutex_destroy(st->lock); - enif_free(st->mailbox); - enif_free(st); -} diff --git a/c_src/tracer/nif_helpers.h b/c_src/tracer/nif_helpers.h deleted file mode 100644 index 2eefec6..0000000 --- a/c_src/tracer/nif_helpers.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2014-2015, Loïc Hoguin -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -#ifndef __NIF_HELPERS_H__ -#define __NIF_HELPERS_H__ - -#include "erl_nif.h" - -#define TO_STRING(i) #i - -// Atoms. - -#define MAX_ATOM_LENGTH 255 - -#define NIF_ATOM_DECL(a) ERL_NIF_TERM atom_ ## a; -#define NIF_ATOM_H_DECL(a) extern ERL_NIF_TERM atom_ ## a; -#define NIF_ATOM_INIT(a) atom_ ## a = enif_make_atom(env, #a); - -// Functions. - -#ifndef NIF_FUNCTION_NAME -#define NIF_FUNCTION_NAME(n) n -#endif - -#define NIF_FUNCTION(f) \ - ERL_NIF_TERM NIF_FUNCTION_NAME(f)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -#define NIF_FUNCTION_ARRAY(f, a) {#f, a, NIF_FUNCTION_NAME(f)}, -#define NIF_FUNCTION_H_DECL(f, a) \ - ERL_NIF_TERM NIF_FUNCTION_NAME(f)(ErlNifEnv*, int, const ERL_NIF_TERM []); - -#define BADARG_IF(cond) if (cond) return enif_make_badarg(env) - -// Resources. - -#ifndef NIF_RES_TYPE -#define NIF_RES_TYPE(t) t -#endif - -#define NIF_RES_DECL(r) ErlNifResourceType* res_ ## r = NULL; -#define NIF_RES_H_DECL(r) \ - extern ErlNifResourceType* res_ ## r; \ - void dtor_ ## r(ErlNifEnv*, void*); \ - typedef struct { \ - NIF_RES_TYPE(r)* v; \ - void* dep; \ - } obj_ ## r; -#define NIF_RES_INIT(r) \ - res_ ## r = enif_open_resource_type(env, NULL, TO_STRING(NIF_RES_TYPE(r)), dtor_ ## r, ERL_NIF_RT_CREATE, NULL); \ - if (!res_ ## r) return -1; - -#define NIF_RES_GET(r, obj) (((obj_ ## r*)obj)->v) -#define NIF_RES_DEP(r, obj) (((obj_ ## r*)obj)->dep) -#define NIF_RES_TO_TERM(r, val, term) NIF_RES_TO_TERM_WITH_DEP(r, val, term, NULL) -#define NIF_RES_TO_TERM_WITH_DEP(r, val, term, dep_res) { \ - obj_ ## r* res = enif_alloc_resource(res_ ## r, sizeof(obj_ ## r)); \ - res->v = val; \ - res->dep = dep_res; \ - term = enif_make_resource(env, res); \ - enif_release_resource(res); \ -} - -// Function generators. - -#define NIF_ATOM_TO_FLAG(a, f) if (enif_is_identical(atom_ ## a, head)) *flags |= f; else -#define NIF_LIST_TO_FLAGS_FUNCTION(f, type, flags_list) \ - int f(ErlNifEnv* env, ERL_NIF_TERM list, type* flags) \ - { \ - ERL_NIF_TERM head; \ - \ - if (!enif_is_list(env, list)) \ - return 0; \ - \ - while (enif_get_list_cell(env, list, &head, &list)) { \ - flags_list(NIF_ATOM_TO_FLAG) /* else */ return 0; \ - } \ - \ - return 1; \ - } - -#define NIF_FLAG_CONS_LIST(a, f) if (flags & f) list = enif_make_list_cell(env, atom_ ## a, list); -#define NIF_FLAGS_TO_LIST_FUNCTION(f, type, flags_list) \ - ERL_NIF_TERM f(ErlNifEnv* env, type flags) \ - { \ - ERL_NIF_TERM list = enif_make_list(env, 0); \ - flags_list(NIF_FLAG_CONS_LIST); \ - return list; \ - } - -#define NIF_ATOM_TO_ENUM(a, e) if (enif_is_identical(atom_ ## a, atom)) { *val = e; return 1; } -#define NIF_ATOM_TO_ENUM_FUNCTION(f, type, enum_list) \ - int f(ErlNifEnv* env, ERL_NIF_TERM atom, type* val) \ - { \ - enum_list(NIF_ATOM_TO_ENUM) \ - \ - return 0; \ - } -#define NIF_ATOM_TO_ENUM_FUNCTION_DECL(f, type) int f(ErlNifEnv*, ERL_NIF_TERM, type*); - -#define NIF_ENUM_TO_ATOM(a, e) if (id == e) return atom_ ## a; -#define NIF_ENUM_TO_ATOM_FUNCTION(f, type, enum_list) \ - ERL_NIF_TERM f(type id) \ - { \ - enum_list(NIF_ENUM_TO_ATOM) \ - return atom_undefined; \ - } -#define NIF_ENUM_TO_ATOM_FUNCTION_DECL(f, type) ERL_NIF_TERM f(type); - -// Threaded NIFs. - -typedef void* nif_thread_arg; - -#ifdef __cplusplus -extern "C" { -#endif - -void* nif_create_main_thread(char*); -void nif_destroy_main_thread(void*); -ERL_NIF_TERM nif_thread_cast(ErlNifEnv*, void (*f)(nif_thread_arg*), int a, ...); -ERL_NIF_TERM nif_thread_call(ErlNifEnv*, ERL_NIF_TERM (*f)(ErlNifEnv*, nif_thread_arg*), int a, ...); - -#ifdef __cplusplus -} -#endif - -#define NIF_CAST_HANDLER(f) static void f(nif_thread_arg* args) -#define NIF_CALL_HANDLER(f) static ERL_NIF_TERM f(ErlNifEnv* env, nif_thread_arg* args) - -#endif diff --git a/c_src/tracer/lg_tracer.c b/c_src/tracer/tpTracerNif.c similarity index 79% rename from c_src/tracer/lg_tracer.c rename to c_src/tracer/tpTracerNif.c index 15df723..540b513 100644 --- a/c_src/tracer/lg_tracer.c +++ b/c_src/tracer/tpTracerNif.c @@ -1,26 +1,8 @@ -// Copyright (c) 2017-Present Pivotal Software, Inc. All rights reserved. -// -// This package, Looking Glass, is double-licensed under the Mozilla -// Public License 1.1 ("MPL") and the Apache License version 2 -// ("ASL"). For the MPL, please see LICENSE-MPL-RabbitMQ. For the ASL, -// please see LICENSE-APACHE2. -// -// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, -// either express or implied. See the LICENSE file for specific language governing -// rights and limitations of this software. -// -// If you have any questions regarding licensing, please contact us at -// info@rabbitmq.com. - -#define NIF_FUNCTION_NAME(f) lg_ ## f - -#include "nif_helpers.h" - -// List of atoms used by this NIF. -// -// @todo We don't use threads so perhaps we should make nif_helpers -// better by splitting concerns into threads/not and have nif_helpers -// decide when to create the _nif_thread_ret atom or not. +#include "erl_nif.h" + +#define NIF_ATOM_DECL(a) ERL_NIF_TERM atom_ ## a; +// #define NIF_ATOM_H_DECL(a) extern ERL_NIF_TERM atom_ ## a; +#define NIF_ATOM_INIT(a) atom_ ## a = enif_make_atom(env, #a); #define NIF_ATOMS(A) \ A(_nif_thread_ret_) \ @@ -70,18 +52,6 @@ NIF_ATOMS(NIF_ATOM_DECL) -// List of functions defined in this NIF. - -#define NIF_FUNCTIONS(F) \ - F(enabled, 3) \ - F(enabled_call, 3) \ - F(enabled_procs, 3) \ - F(enabled_running_procs, 3) \ - F(enabled_send, 3) \ - F(trace, 5) - -NIF_FUNCTIONS(NIF_FUNCTION_H_DECL) - static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { NIF_ATOMS(NIF_ATOM_INIT) @@ -102,8 +72,7 @@ static void unload(ErlNifEnv* env, void* priv_data) // enabled(TraceTag, TracerState, Tracee) -NIF_FUNCTION(enabled) -{ +static ERL_NIF_TERM enabled(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM tracers, value; ErlNifPid tracer; @@ -135,14 +104,13 @@ NIF_FUNCTION(enabled) return atom_discard; } -NIF_FUNCTION(enabled_call) -{ +static ERL_NIF_TERM enabled_call(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { + // We always want both call and return_to. return atom_trace; } -NIF_FUNCTION(enabled_procs) -{ +static ERL_NIF_TERM enabled_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM mode; // We only want the spawn and exit events when 'profile' mode @@ -158,22 +126,19 @@ NIF_FUNCTION(enabled_procs) return atom_trace; } -NIF_FUNCTION(enabled_running_procs) -{ +static ERL_NIF_TERM enabled_running_procs(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { // We always want both in and out. return atom_trace; } -NIF_FUNCTION(enabled_send) -{ +static ERL_NIF_TERM enabled_send(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { + // We always want both send and send_to_non_existing_process. return atom_trace; } // trace(TraceTag, TracerState, Tracee, TraceTerm, Opts) - -NIF_FUNCTION(trace) -{ +static ERL_NIF_TERM trace(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM tracers, head, ts, extra, mspec, msg; ErlNifPid tracer; unsigned int nth; @@ -248,8 +213,13 @@ NIF_FUNCTION(trace) return atom_ok; } -static ErlNifFunc nif_funcs[] = { - NIF_FUNCTIONS(NIF_FUNCTION_ARRAY) +static ErlNifFunc nifFuns[] = { + {"enabled", 3, enabled}, + {"enabled_call", 3, enabled_call}, + {"enabled_procs", 3, enabled_procs}, + {"enabled_running_procs", 3, enabled_running_procs}, + {"enabled_send", 3, enabled_send}, + {"trace", 5, trace}, }; -ERL_NIF_INIT(tpTracerNif, nif_funcs, load, NULL, upgrade, unload) +ERL_NIF_INIT(tpTracerNif, nifFuns, load, NULL, upgrade, unload) \ No newline at end of file