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;
}