Skip to content

Instantly share code, notes, and snippets.

@mikesart
Created June 9, 2017 00:08
Show Gist options
  • Save mikesart/7c915b20df4af2cad7f0d0375be2d208 to your computer and use it in GitHub Desktop.
Save mikesart/7c915b20df4af2cad7f0d0375be2d208 to your computer and use it in GitHub Desktop.
quick / simple pthread test app
/*
* pthread example test app for lldb, from Michael Sartain's post at
* http://linux-debugger-bits.blogspot.com/2013/07/linux-pthread-test-app-with-lldb.html
*
* clang -Wall -g -o mikesart_pthread -lpthread mikesart_pthread.c
*/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
uint32_t g_sleep_time = 4;
__thread pid_t g_tls = -1;
__thread char g_threadname[32];
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;
}
pid_t gettid()
{
return (pid_t)syscall(SYS_gettid);
}
void setname(const char *name)
{
pthread_setname_np(pthread_self(), g_threadname);
}
void trace_marker( const char *buf )
{
int fd;
static const char filename[] = "/sys/kernel/debug/tracing/trace_marker";
fd = open( filename, O_WRONLY );
if ( fd >= 0 )
{
write( fd, buf, strlen( buf ) );
close( fd );
}
else
{
printf("trace_marker failed\n");
}
}
void logit(const char *format, ...)
{
va_list args;
char buf[1024];
snprintf(buf, sizeof(buf), "'%s' [#%d LWP:%d 0x%lx] %s", g_threadname, g_tls, gettid(), (unsigned long)pthread_self(), format);
va_start (args, format);
vprintf (buf, args);
va_end (args);
trace_marker( buf );
}
void *thread_proc(void *arg)
{
g_tls = (int)(intptr_t)arg;
snprintf(g_threadname, sizeof(g_threadname), "thread_%d", g_tls);
logit("pthread_setname_np('%s')\n", g_threadname);
setname(g_threadname);
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);
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;
snprintf(g_threadname, sizeof(g_threadname), "thread_main");
setname(g_threadname);
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