s = pthread_mutex_unlock(&thread_mutex); if (s != 0) errExitEN(s, "pthread_mutex_unlock");
s = pthread_cond_signal(&thread_died); if (s != 0) errExitEN(s, "pthread_cond_signal");
returnNULL; }
intmain(int argc, char *argv[]) { int s, idx;
thread = calloc(argc - 1, sizeof(*thread)); if (thread == NULL) errExit("calloc"); for (idx = 0; idx < argc-1; ++idx) { thread[idx].sleep_time = getInt(argv[idx+1], GN_NONNEG, NULL); thread[idx].state = TS_ALIVE; s = pthread_create(&thread[idx].tid, NULL, thread_func, &idx); if (s != 0) errExitEN(s, "pthread_create"); }
tot_threads = argc - 1; num_live = tot_threads;
while (num_live > 0) { s = pthread_mutex_lock(&thread_mutex); if (s != 0) errExitEN(s, "pthread_mutex_lock");
while (num_unjoined == 0) { s = pthread_cond_wait(&thread_died, &thread_mutex); if (s != 0) errExitEN(s, "pthread_cond_wait"); }
for (idx = 0; idx < tot_threads; ++idx) { if (thread[idx].state == TS_TERMINATED) { s = pthread_join(thread[idx].tid, NULL); if (s != 0) errExitEN(s, "pthread_join");
Any integer can be cast to any pointer type. Except for the null pointer constants such as NULL (which doesn’t need a cast), the result is implementation-defined, may not be correctly aligned, may not point to an object of the referenced type, and may be a trap representation.
Any pointer type can be cast to any integer type. The result is implementation-defined, even for null pointer values (they do not necessarily result in the value zero). If the result cannot be represented in the target type, the behavior is undefined (unsigned integers do not implement modulo arithmetic on a cast from pointer)