/***************************************************************************** File: schedBug.C Contents: FreeBSD Scheduling Bug Illustrator This program SHOULD print "Marking Time : 1", etc. However, the thread scheduler appears to NOT schedule the markTimeThread because the ioThread is so busy. If you uncomment the "::pthread_yield()" it works a little better. Ideally, you should get a print every second. g++ -o schedBug -D_REENTRANT -D_THREAD_SAFE -g -Wall schedBug.C -pthread *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #define LENGTH (1024 * 1024) #ifndef NUM_THREADS #define NUM_THREADS 10 #endif static int done = 0; void * ioThread(void *arg) { char *data; char filename[30]; int file; assert((data = malloc(LENGTH)) != NULL); memset(data, 0, LENGTH); sprintf(filename, "scrap.%d", (int)arg); file = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0666); assert(file >= 0); while (done == 0) { write(file, data, LENGTH); // // Uncomment the next line to make things a bit better // // ::pthread_yield(); // lseek(file, (off_t)0, SEEK_SET); } close(file); unlink(filename); return (NULL); } void * markTimeThread(void *arg) { struct timeval timeout; time_t start; start = time(0); while (done == 0) { timeout.tv_sec = 1; timeout.tv_usec = 0; select(0, 0, 0, 0, &timeout); printf("Marking Time: %lu\n", (unsigned long)(time(0) - start)); } return (NULL); } void sighandler(int sig, siginfo_t *info, ucontext_t *ucp) { if (sig == SIGINT) done = 1; } int main(int argc, char *argv[]) { // Set up Thread Arguments struct sigaction act; pthread_t tid[NUM_THREADS]; pthread_attr_t attr; int prio; int i; sigfillset(&act.sa_mask); act.sa_sigaction = sighandler; act.sa_flags = SA_SIGINFO; assert(sigaction(SIGINT, &act, NULL) == 0); sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGINT); assert(sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL) == 0); assert(pthread_attr_init(&attr) == 0); assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0); // Spawn markTimeThread assert(pthread_create(&tid[0], &attr, markTimeThread, 0) == 0); prio = pthread_getprio(tid[0]); assert(pthread_setprio(tid[0], prio + 1) == 0); pthread_set_name_np(tid[0], "markTimeThread"); // Spawn ioThreads for (i = 1; i < NUM_THREADS; i++) { assert(pthread_create(&tid[i], &attr, ioThread, (void *)i) == 0); pthread_set_name_np(tid[i], "ioThread"); } /* main() goes away until all the threads have exited. */ while (done == 0) { sleep(1); } return (EXIT_SUCCESS); }