void lttngh_ActivityIdCreate()

in src/LttngActivityHelpers.c [77:144]


void lttngh_ActivityIdCreate(void *pNewActivityId) {
  static pthread_mutex_t StaticMutex = PTHREAD_MUTEX_INITIALIZER;
  static struct lttngh_ActivityRoot StaticRoot; // Generator ID.
  static uint32_t StaticPool; // Incremented as threads allocate pools.

  // Return a 16-byte value that is unlikely to conflict with other values
  // in the same trace. A UUID would work, but would be more expensive than
  // we want. Instead, generate a 3-part locally-unique id:
  // - The top 64 bits distinguish our generator from other generators that
  //   might also be writing to the same trace.
  // - The next 32 bits are a pool number. This distinguishes between
  //   threads using our generator (each thread allocates a pool as needed).
  //   If we run out of pools, we reseed the top 64 bits.
  // - The next 32 bits are assigned by incrementing a thread-local value.
  //   If this overflows, the thread allocates a new pool.
  struct lttngh_ThreadInfo *pInfo = &ThreadInfo;
  if (caa_unlikely(pInfo->ThreadActivityNext[3] == 0)) {
    // Allocate a new pool for our thread.

    struct lttngh_ActivityRoot localRoot;
    uint32_t localPool;
    char localRootIsValid;

    localPool = __atomic_load_n(&StaticPool, __ATOMIC_RELAXED);
    if (localPool != 0) {
      // Optimistically assume that we won't need to generate a root.
      localRootIsValid = 0;
    } else {
      // Assume that we'll need a new root.
      ActivityRootCreate(&localRoot);
      localRootIsValid = 1;
    }

    pthread_mutex_lock(&StaticMutex);

    localPool = StaticPool;
    if (caa_unlikely(localPool == 0 && !localRootIsValid)) {
      // StaticPool became 0, so we need to generate a root after all.
      pthread_mutex_unlock(&StaticMutex);
      ActivityRootCreate(&localRoot);
      pthread_mutex_lock(&StaticMutex);
      localPool = StaticPool;
    }

    StaticPool = (localPool + 1) & 0x3fffffff;
    if (localPool == 0) {
      // Update the global root with our newly-generated root.
      StaticRoot = localRoot;
    } else {
      // Update our root from the global root.
      localRoot = StaticRoot;
    }

    pthread_mutex_unlock(&StaticMutex);

    assert(0 == (localPool & 0xc0000000)); // Memory corruption?
    pInfo->ThreadActivityNext[0] = localRoot.Root0;
    pInfo->ThreadActivityNext[1] = localRoot.Root1;

    // Set the GUID variant bits to "RFC4122", even though we aren't really a
    // GUID.
    pInfo->ThreadActivityNext[2] = HostToBigEndian32(localPool | 0x80000000);
  }

  memcpy(pNewActivityId, pInfo->ThreadActivityNext,
         sizeof(pInfo->ThreadActivityNext));
  pInfo->ThreadActivityNext[3] += 1;
}