Parcourir la source

ft: 代码修改

master
SisMaker il y a 3 ans
Parent
révision
28544d5e6e
3 fichiers modifiés avec 21 ajouts et 385 suppressions
  1. +0
    -195
      c_src/tracer/nif_helpers.c
  2. +0
    -139
      c_src/tracer/nif_helpers.h
  3. +21
    -51
      c_src/tracer/tpTracerNif.c

+ 0
- 195
c_src/tracer/nif_helpers.c Voir le fichier

@ -1,195 +0,0 @@
// Copyright (c) 2014-2015, Loïc Hoguin <essen@ninenines.eu>
//
// 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 <sys/queue.h>
#include <stdarg.h>
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);
}

+ 0
- 139
c_src/tracer/nif_helpers.h Voir le fichier

@ -1,139 +0,0 @@
// Copyright (c) 2014-2015, Loïc Hoguin <essen@ninenines.eu>
//
// 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

c_src/tracer/lg_tracer.c → c_src/tracer/tpTracerNif.c Voir le fichier

@ -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)

Chargement…
Annuler
Enregistrer