/* * Please compile this for x86, even if you're running a 64-bit kernel * gcc -O2 -m32 crazylock.c -o crazylock */ #define _GNU_SOURCE 1 #include #include #include #include #include #ifndef DEFAULT_NR_THREADS # define DEFAULT_NR_THREADS 3U #endif #ifndef PIN_TO_CPU # define PIN_TO_CPU 0 #endif static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; static size_t fodder_size; static unsigned char *fodder; static void cache_get(const unsigned int n) { assert(rwlock.__data.__nr_readers < n); assert(rwlock.__data.__nr_writers_queued < n); pthread_rwlock_rdlock(&rwlock); assert(rwlock.__data.__nr_readers <= n); assert(rwlock.__data.__nr_writers_queued < n); fodder[rand() % fodder_size]++; pthread_rwlock_unlock(&rwlock); assert(rwlock.__data.__nr_readers < n); assert(rwlock.__data.__nr_writers_queued < n); } static void * thread_main(void *n_ptr) { const unsigned int n = (const unsigned int) n_ptr; for (;;) { cache_get(n); } /* NOTREACHED */ return NULL; } static void spawn_threads(pthread_t *threads, unsigned int n) { unsigned int i = n; while (i-- > 0U) { pthread_create(&threads[i], NULL, thread_main, (void *) n); #if defined(CPU_SET) && PIN_TO_CPU != 0 cpu_set_t cpuset; CPU_ZERO(&cpuset); (void) CPU_SET(i, &cpuset); pthread_setaffinity_np(threads[i], sizeof(cpuset), &cpuset); #endif } } static void usage(void) { printf("Usage: crazylock \n", DEFAULT_NR_THREADS); } int main(int argc, char *argv[]) { pthread_t *threads; unsigned int i; unsigned int n = DEFAULT_NR_THREADS; if (argc > 1) { n = (unsigned int) strtoul(argv[1], NULL, 10); if (n == 0U) { usage(); } } assert((threads = malloc((size_t) n * sizeof *threads)) != NULL); fodder_size = 1024U * 1024U * 1024U; assert((fodder = malloc(fodder_size)) != NULL); spawn_threads(threads, n); i = n; while (i-- > 0U) { pthread_join(threads[i], NULL); } /* NOTREACHED */ free(threads); return 0; }