| #include "test.h" | |
| enum { | |
| NUMTHREADS = 10000 | |
| }; | |
| static long done = 0; | |
| void * func(void * arg) | |
| { | |
| sched_yield(); | |
| InterlockedIncrement(&done); | |
| return (void *) 0; | |
| } | |
| int | |
| main() | |
| { | |
| pthread_t t[NUMTHREADS]; | |
| pthread_attr_t attr; | |
| int i; | |
| unsigned int notUnique = 0, | |
| totalHandles = 0, | |
| reuseMax = 0, | |
| reuseMin = NUMTHREADS; | |
| assert(pthread_attr_init(&attr) == 0); | |
| assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0); | |
| for (i = 0; i < NUMTHREADS; i++) | |
| { | |
| assert(pthread_create(&t[i], &attr, func, NULL) == 0); | |
| } | |
| while (NUMTHREADS > InterlockedExchangeAdd((LPLONG)&done, 0L)) | |
| Sleep(100); | |
| Sleep(100); | |
| /* | |
| * Analyse reuse by computing min and max number of times pthread_create() | |
| * returned the same pthread_t value. | |
| */ | |
| for (i = 0; i < NUMTHREADS; i++) | |
| { | |
| if (t[i]) | |
| { | |
| unsigned int j, thisMax; | |
| thisMax = t[i]; | |
| for (j = i+1; j < NUMTHREADS; j++) | |
| if (__pth_gpointer_locked (t[i]) == __pth_gpointer_locked (t[j])) | |
| { | |
| if (t[i] == t[j]) | |
| notUnique++; | |
| if (thisMax < t[j]) | |
| thisMax = t[j]; | |
| t[j] = 0; | |
| } | |
| if (reuseMin > thisMax) | |
| reuseMin = thisMax; | |
| if (reuseMax < thisMax) | |
| reuseMax = thisMax; | |
| } | |
| } | |
| for (i = 0; i < NUMTHREADS; i++) | |
| if (t[i] != 0) | |
| totalHandles++; | |
| /* | |
| * pthread_t reuse counts start at 0, so we need to add 1 | |
| * to the max and min values derived above. | |
| */ | |
| printf("For %d total threads:\n", NUMTHREADS); | |
| printf("Non-unique IDs = %d\n", notUnique); | |
| printf("Reuse maximum = %d\n", reuseMax + 1); | |
| printf("Reuse minimum = %d\n", reuseMin + 1); | |
| printf("Total handles = %d\n", totalHandles); | |
| return 0; | |
| } |