Created
November 27, 2023 11:46
-
-
Save johnsonjh/d49145a83335236318bd38d8f8456954 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#define _ALL_SOURCE | |
#include <pthread.h> | |
#include <stdarg.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <time.h> | |
#include <unistd.h> | |
static uint32_t g_sleep_time = 4; | |
_Thread_local pid_t g_tls = -1; | |
static uint64_t | |
get_time_microseconds () | |
{ | |
struct timespec ts; | |
if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0) | |
return ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000ULL; | |
return 0; | |
} | |
static void | |
logit (const char *format, ...) | |
{ | |
va_list args; | |
char buf[1024]; | |
snprintf (buf, sizeof (buf), "[#%2d LWP:%d 0x%lx] %s", g_tls + 1, gettid (), | |
(unsigned long)pthread_self (), format); | |
va_start (args, format); | |
vprintf (buf, args); | |
va_end (args); | |
} | |
static void * | |
thread_proc (void *arg) | |
{ | |
g_tls = (int)(intptr_t)arg; | |
uint64_t t0 = get_time_microseconds (); | |
if (!t0) | |
{ | |
logit ("sleep(%u)\n", g_sleep_time); | |
sleep (g_sleep_time); | |
} | |
else | |
{ | |
uint64_t last = t0; | |
logit ("busy loop %u\n", g_sleep_time); | |
for (;;) | |
{ | |
uint64_t t1 = get_time_microseconds (); | |
if (t1 - t0 >= g_sleep_time * 1000000) | |
break; | |
if (t1 - last >= 1000000) | |
{ | |
logit ("%.2f seconds\n", (t1 - t0) / 1000000.0f); | |
last = t1; | |
} | |
} | |
} | |
pid_t tid = gettid (); | |
logit ("pthread_exit(%d)\n", tid); | |
pthread_exit ((void *)(intptr_t)tid); | |
/* unreachable */ | |
return 0; | |
} | |
int | |
main (int argc, char *argv[]) | |
{ | |
pthread_t threadids[256]; | |
static const size_t max_threads = sizeof (threadids) / sizeof (threadids[0]); | |
size_t num_threads = (argc > 1) ? atoi (argv[1]) : 6; | |
if (num_threads < 2) | |
num_threads = 2; | |
else if (num_threads > max_threads) | |
num_threads = max_threads; | |
logit ("num_threads:%zu\n", num_threads); | |
for (size_t i = 0; i < num_threads; i++) | |
{ | |
int err = pthread_create (&(threadids[i]), NULL, &thread_proc, | |
(void *)(intptr_t)i); | |
logit ("pthread_create:%d (%s) pthread_t:%lx\n", err, strerror (err), | |
threadids[i]); | |
} | |
sleep (1); | |
for (size_t i = 0; i < num_threads; i++) | |
{ | |
logit ("Waiting for thread #%zu\n", i); | |
void *status = NULL; | |
int rc = pthread_join (threadids[i], &status); | |
logit ("Thread #%zu rc:%d status:%d\n", i, rc, (int)(intptr_t)status); | |
} | |
logit ("done.\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment