int lttngh_RegisterProvider()

in src/LttngHelpers.c [465:528]


int lttngh_RegisterProvider(
    lttngh_registration* pRegistration,
    lttngh_ust_probe_desc *pProbeDesc,
    struct lttng_ust_tracepoint **pTracepointStart,
    struct lttng_ust_tracepoint **pTracepointStop,
    lttngh_ust_event_desc const **pEventDescStart,
    lttngh_ust_event_desc const **pEventDescStop)
{
    int err;
    int volatile* const pIsRegistered = lttngh_REGISTRATION_STATE(*pRegistration);

    // Note: not intended to support multithreaded or ref-counted registration.
    // pRegistration is used to make it safe to call Unregister on an
    // unregistered lib and to help detect misuse, not to make this thread-safe.
    if (__atomic_exchange_n(pIsRegistered, 1, __ATOMIC_RELAXED) != 0)
    {
        err = EEXIST;
        ProviderError(pProbeDesc, err,
                      "provider already registered.");
    }
    else
    {
        lttngh_ust_event_desc const **const pEventDescLast =
            (lttngh_ust_event_desc const **)FixArray(
                (void const **)pEventDescStart, (void const **)pEventDescStop);
        pProbeDesc->event_desc = pEventDescStart;
        pProbeDesc->nr_events = (unsigned)(pEventDescLast - pEventDescStart);
#if lttngh_UST_VER >= 213
        pRegistration->registered_probe = lttng_ust_probe_register(pProbeDesc);
        pRegistration->tracepoint_start = pTracepointStart;
        err = pRegistration->registered_probe ? 0 : ENOMEM;
#else // lttngh_UST_VER
        err = lttng_probe_register(pProbeDesc);
#endif // lttngh_UST_VER
        if (err != 0)
        {
            ProviderError(pProbeDesc, err,
                          "lttng_probe_register failed."
                          " (Registration of multiple providers having the same name is not supported.)");
            __atomic_exchange_n(pIsRegistered, 0, __ATOMIC_RELAXED);
        }
        else
        {
            struct lttng_ust_tracepoint *const *const pTracepointLast =
                (struct lttng_ust_tracepoint *const *)FixArray(
                    (void const **)pTracepointStart, (void const **)pTracepointStop);

            // May fail for out-of-memory. Continue anyway.
            err = lttngh_ust_tracepoint_module_register(pTracepointStart, (int)(pTracepointLast - pTracepointStart));
            if (err != 0)
            {
#if lttngh_UST_VER >= 213
                lttng_ust_probe_unregister(pRegistration->registered_probe);
#else // lttngh_UST_VER
                lttng_probe_unregister(pProbeDesc);
#endif // lttngh_UST_VER

                __atomic_exchange_n(pIsRegistered, 0, __ATOMIC_RELAXED);
            }
        }
    }

    return err;
}