int lttngh_EventProbe()

in src/LttngHelpers.c [1244:1467]


int lttngh_EventProbe(
    struct lttng_ust_tracepoint *pTracepoint,
    struct lttngh_DataDesc *pDataDesc,
    unsigned cDataDesc,
    void *pCallerIp)
{
    int err = 0;
    struct lttng_ust_tracepoint_probe *pTpProbe;
    unsigned char transcodeScratchOnStack[256] __attribute__((aligned(2)));

    struct lttngh_EventProbeContext context = {
        .maxAlign = 0, // 0 means we haven't computed event size yet.
        .cbData = 0,
        .pbTranscodeScratch = transcodeScratchOnStack,
        .cbTranscodeScratch = sizeof(transcodeScratchOnStack) };

    if (pCallerIp == NULL)
    {
        pCallerIp = lttngh_IP_PARAM;
    }

    lttng_ust_urcu_read_lock();
    pTpProbe = lttng_ust_rcu_dereference(pTracepoint->probes);
    if (caa_likely(pTpProbe))
    {
        do
        {
            lttngh_ust_event_common* const pEvent = (lttngh_ust_event_common* const)pTpProbe->data;

#if lttngh_UST_VER >= 213

            if (caa_likely(pEvent->type == LTTNG_UST_EVENT_TYPE_RECORDER))
            {
                struct lttng_ust_event_recorder* pEventRecorder = (struct lttng_ust_event_recorder*)pEvent->child;
                struct lttng_ust_channel_common* pChannelCommon = pEventRecorder->chan->parent;

                if (
#ifdef TP_SESSION_CHECK // Are we building statedump?
                    session != pChannelCommon->session ||
#endif // TP_SESSION_CHECK
                    caa_unlikely(!CMM_ACCESS_ONCE(pChannelCommon->session->active)) ||
                    caa_unlikely(!CMM_ACCESS_ONCE(pChannelCommon->enabled)))
                {
                    continue;
                }

                if (caa_unlikely(!CMM_ACCESS_ONCE(pEvent->enabled)))
                {
                    continue;
                }

                if (caa_unlikely(CMM_ACCESS_ONCE(pEvent->eval_filter)) &&
                    !caa_unlikely(EventProbeFilter(pEvent, pCallerIp, pDataDesc, cDataDesc)))
                {
                    continue;
                }

                // Compute event size the first time through.
                if (caa_likely(context.maxAlign == 0))
                {
                    err = EventProbeComputeSizes(&context, pDataDesc, cDataDesc);
                    if (err != 0)
                    {
                        goto Done;
                    }
                }

                struct lttng_ust_channel_buffer* pChannel = pEventRecorder->chan;

                struct lttng_ust_ring_buffer_ctx bufferContext;
                lttng_ust_ring_buffer_ctx_init(&bufferContext, pEventRecorder, context.cbData, context.maxAlign, pCallerIp);

                int const reserveResult = pChannel->ops->event_reserve(&bufferContext);
                if (caa_unlikely(reserveResult < 0))
                {
                    err = reserveResult;
                }
                else
                {
                    unsigned i;
                    for (i = 0; i != cDataDesc; i += 1)
                    {
                        uint16_t cbUtf8Written;
                        switch (pDataDesc[i].Type)
                        {
                        case lttngh_DataType_String8:
                            pChannel->ops->event_strcpy(&bufferContext, pDataDesc[i].Data, pDataDesc[i].Size);
                            break;

                        case lttngh_DataType_StringUtf16Transcoded:
                        case lttngh_DataType_StringUtf32Transcoded:
                            cbUtf8Written = EventProbeTranscodeString(&context, &pDataDesc[i]);
                            pChannel->ops->event_write(&bufferContext, context.pbTranscodeScratch, cbUtf8Written + 1u, pDataDesc[i].Alignment);
                            break;

                        case lttngh_DataType_SequenceUtf16Transcoded:
                        case lttngh_DataType_SequenceUtf32Transcoded:
                            cbUtf8Written = EventProbeTranscodeSequence(&context, &pDataDesc[i]);
                            pChannel->ops->event_write(&bufferContext, context.pbTranscodeScratch, sizeof(uint16_t) + cbUtf8Written, pDataDesc[i].Alignment);
                            break;

                        default:
                            pChannel->ops->event_write(&bufferContext, pDataDesc[i].Data, pDataDesc[i].Size, pDataDesc[i].Alignment);
                            break;
                        }
                    }

                    pChannel->ops->event_commit(&bufferContext);
                }
            }
            else if (caa_likely(CMM_ACCESS_ONCE(pEvent->enabled)))
            {
                if (caa_likely(pEvent->type == LTTNG_UST_EVENT_TYPE_NOTIFIER) ||
                    caa_unlikely(CMM_ACCESS_ONCE(pEvent->eval_filter)))
                {
                    (void)EventProbeFilter(pEvent, pCallerIp, pDataDesc, cDataDesc);
                }
            }

#else // lttngh_UST_VER

            struct lttng_channel const *const pChannel = pEvent->chan;

            if (caa_likely(CMM_ACCESS_ONCE(pChannel->session->active)) &&
                caa_likely(CMM_ACCESS_ONCE(pChannel->enabled)) &&
                caa_likely(CMM_ACCESS_ONCE(pEvent->enabled)) &&
#ifdef TP_SESSION_CHECK // Are we building statedump?
                session == pChannel->session &&
#endif // TP_SESSION_CHECK
                (caa_likely(cds_list_empty(&pEvent->bytecode_runtime_head)) ||
                 caa_unlikely(EventProbeFilter(pEvent, pDataDesc, cDataDesc))))
            {
                // Compute event size the first time through.
                if (caa_likely(context.maxAlign == 0))
                {
                    err = EventProbeComputeSizes(&context, pDataDesc, cDataDesc);
                    if (err != 0)
                    {
                        goto Done;
                    }
                }

#if lttngh_UST_VER >= 208
                struct lttng_stack_ctx stackContext;
                memset(&stackContext, 0, sizeof(stackContext));

                stackContext.event = pEvent;
                stackContext.chan_ctx = lttng_ust_rcu_dereference(pChannel->ctx);
                stackContext.event_ctx = lttng_ust_rcu_dereference(pEvent->ctx);
#endif // lttngh_UST_VER >= 208

                struct lttng_ust_lib_ring_buffer_ctx bufferContext;
                lib_ring_buffer_ctx_init(&bufferContext, pChannel->chan, pEvent,
                    context.cbData, (int)context.maxAlign, -1, pChannel->handle
#if lttngh_UST_VER >= 208
                                         ,
                                         &stackContext
#endif // lttngh_UST_VER >= 208
                );
                bufferContext.ip = pCallerIp;

                int const reserveResult = pChannel->ops->event_reserve(&bufferContext, pEvent->id);
                if (caa_unlikely(reserveResult < 0))
                {
                    err = reserveResult;
                }
                else
                {
                    unsigned i;
                    for (i = 0; i != cDataDesc; i += 1)
                    {
                        uint16_t cbUtf8Written;
#if lttngh_UST_RING_BUFFER_NATURAL_ALIGN
                        lib_ring_buffer_align_ctx(&bufferContext, pDataDesc[i].Alignment);
#endif // lttngh_UST_RING_BUFFER_NATURAL_ALIGN
                        switch (pDataDesc[i].Type)
                        {
                        case lttngh_DataType_String8:
                            if (pChannel->ops->u.has_strcpy)
                            {
                                pChannel->ops->event_strcpy(&bufferContext, (char const*)pDataDesc[i].Data, pDataDesc[i].Size);
                            }
                            else
                            {
                                pChannel->ops->event_write(&bufferContext, pDataDesc[i].Data, pDataDesc[i].Size);
                            }
                            break;

                        case lttngh_DataType_StringUtf16Transcoded:
                        case lttngh_DataType_StringUtf32Transcoded:
                            cbUtf8Written = EventProbeTranscodeString(&context, &pDataDesc[i]);
                            pChannel->ops->event_write(&bufferContext, context.pbTranscodeScratch, cbUtf8Written + 1u);
                            break;

                        case lttngh_DataType_SequenceUtf16Transcoded:
                        case lttngh_DataType_SequenceUtf32Transcoded:
                            cbUtf8Written = EventProbeTranscodeSequence(&context, &pDataDesc[i]);
                            pChannel->ops->event_write(&bufferContext, context.pbTranscodeScratch, sizeof(uint16_t) + cbUtf8Written);
                            break;

                        default:
                            pChannel->ops->event_write(&bufferContext, pDataDesc[i].Data, pDataDesc[i].Size);
                            break;
                        }
                    }

                    pChannel->ops->event_commit(&bufferContext);
                }
            }
#endif // lttngh_UST_VER
        } while ((++pTpProbe)->data);
    }

Done:

    lttng_ust_urcu_read_unlock();

    if (caa_unlikely(context.pbTranscodeScratch != transcodeScratchOnStack))
    {
        free(context.pbTranscodeScratch);
    }

    return err;
}