/* Allocate any resouces for THREAD. The new kernel thread should not be eligible to be scheduled. */ int __pthread_thread_alloc (struct __pthread *thread) { if (thread->have_kernel_resources) return 0; error_t err; err = create_wakeupmsg (thread); if (err) return err; /* If there are no pthreads in the system then the pthread library is bootstrapping and the main thread must create initialize itself. The thread itself is already running, it just has not pthread context. We want to reuse what it already has (including the kernel thread), however, we must determine which thread is the main thread. We cannot test if __pthread_total is one as we later decrement before creating the signal thread. Currently, we check if __pthread_num_threads--the number of allocated thread structures--is one. __pthread_alloc has already been called in __pthread_create_internal for us. This predicate could be improved, however, it is sufficient for now. */ if (__pthread_num_threads == 1) { assert (__pthread_total == 0); thread->kernel_thread = __mach_thread_self (); /* We implicitly hold a reference drop the one that we just acquired. */ __mach_port_deallocate (__mach_task_self (), thread->kernel_thread); } else { err = __thread_create (__mach_task_self (), &thread->kernel_thread); if (err) return EAGAIN; } thread->have_kernel_resources = 1; return 0; }
static error_t update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale) { error_t err; if (profile_thread == MACH_PORT_NULL) { /* Set up the profiling collector thread. */ static void profile_waiter (void); err = __thread_create (__mach_task_self (), &profile_thread); if (! err) err = __mach_setup_thread (__mach_task_self (), profile_thread, &profile_waiter, NULL, NULL); } else err = 0; if (! err) { err = __task_enable_pc_sampling (__mach_task_self (), &profile_tick, SAMPLED_PC_PERIODIC); if (!err && sample_scale == 0) /* Profiling was not turned on, so the collector thread was suspended. Resume it. */ err = __thread_resume (profile_thread); if (! err) { samples = sample_buffer; maxsamples = size / sizeof *sample_buffer; pc_offset = offset; sample_scale = scale; /* Calculate a good period for the collector thread. From TICK and the kernel buffer size we get the length of time it takes to fill the buffer; translate that to milliseconds for mach_msg, and chop it in half for general lag factor. */ collector_timeout = MAX_PC_SAMPLES * profile_tick / 1000 / 2; } } return err; }