in source/posix/thread.c [207:356]
int aws_thread_launch(
struct aws_thread *thread,
void (*func)(void *arg),
void *arg,
const struct aws_thread_options *options) {
pthread_attr_t attributes;
pthread_attr_t *attributes_ptr = NULL;
int attr_return = 0;
int allocation_failed = 0;
bool is_managed_thread = options != NULL && options->join_strategy == AWS_TJS_MANAGED;
if (is_managed_thread) {
thread->detach_state = AWS_THREAD_MANAGED;
}
if (options) {
attr_return = pthread_attr_init(&attributes);
if (attr_return) {
goto cleanup;
}
attributes_ptr = &attributes;
if (options->stack_size > PTHREAD_STACK_MIN) {
attr_return = pthread_attr_setstacksize(attributes_ptr, options->stack_size);
if (attr_return) {
goto cleanup;
}
}
/* AFAIK you can't set thread affinity on apple platforms, and it doesn't really matter since all memory
* NUMA or not is setup in interleave mode.
* Thread afinity is also not supported on Android systems, and honestly, if you're running android on a NUMA
* configuration, you've got bigger problems. */
#if AWS_AFFINITY_METHOD == AWS_AFFINITY_METHOD_PTHREAD_ATTR
if (options->cpu_id >= 0) {
AWS_LOGF_INFO(
AWS_LS_COMMON_THREAD,
"id=%p: cpu affinity of cpu_id %d was specified, attempting to honor the value.",
(void *)thread,
options->cpu_id);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET((uint32_t)options->cpu_id, &cpuset);
attr_return = pthread_attr_setaffinity_np(attributes_ptr, sizeof(cpuset), &cpuset);
if (attr_return) {
AWS_LOGF_ERROR(
AWS_LS_COMMON_THREAD,
"id=%p: pthread_attr_setaffinity_np() failed with %d.",
(void *)thread,
errno);
goto cleanup;
}
}
#endif /* AWS_AFFINITY_METHOD == AWS_AFFINITY_METHOD_PTHREAD_ATTR */
}
struct thread_wrapper *wrapper =
(struct thread_wrapper *)aws_mem_calloc(thread->allocator, 1, sizeof(struct thread_wrapper));
if (!wrapper) {
allocation_failed = 1;
goto cleanup;
}
if (options && options->cpu_id >= 0) {
wrapper->membind = true;
}
wrapper->thread_copy = *thread;
wrapper->allocator = thread->allocator;
wrapper->func = func;
wrapper->arg = arg;
/*
* Increment the count prior to spawning the thread. Decrement back if the create failed.
*/
if (is_managed_thread) {
aws_thread_increment_unjoined_count();
}
attr_return = pthread_create(&thread->thread_id, attributes_ptr, thread_fn, (void *)wrapper);
if (attr_return) {
if (is_managed_thread) {
aws_thread_decrement_unjoined_count();
}
goto cleanup;
}
#if AWS_AFFINITY_METHOD == AWS_AFFINITY_METHOD_PTHREAD
/* If we don't have pthread_attr_setaffinity_np, we may
* still be able to set the thread affinity after creation. */
if (options && options->cpu_id >= 0) {
AWS_LOGF_INFO(
AWS_LS_COMMON_THREAD,
"id=%p: cpu affinity of cpu_id %d was specified, attempting to honor the value.",
(void *)thread,
options->cpu_id);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET((uint32_t)options->cpu_id, &cpuset);
attr_return = pthread_setaffinity_np(thread->thread_id, sizeof(cpuset), &cpuset);
if (attr_return) {
AWS_LOGF_ERROR(
AWS_LS_COMMON_THREAD, "id=%p: pthread_setaffinity_np() failed with %d.", (void *)thread, errno);
goto cleanup;
}
}
#endif /* AWS_AFFINITY_METHOD == AWS_AFFINITY_METHOD_PTHREAD */
/*
* Managed threads need to stay unjoinable from an external perspective. We'll handle it after thread function
* completion.
*/
if (is_managed_thread) {
aws_thread_clean_up(thread);
} else {
thread->detach_state = AWS_THREAD_JOINABLE;
}
cleanup:
if (attributes_ptr) {
pthread_attr_destroy(attributes_ptr);
}
if (attr_return == EINVAL) {
return aws_raise_error(AWS_ERROR_THREAD_INVALID_SETTINGS);
}
if (attr_return == EAGAIN) {
return aws_raise_error(AWS_ERROR_THREAD_INSUFFICIENT_RESOURCE);
}
if (attr_return == EPERM) {
return aws_raise_error(AWS_ERROR_THREAD_NO_PERMISSIONS);
}
if (allocation_failed || attr_return == ENOMEM) {
return aws_raise_error(AWS_ERROR_OOM);
}
return AWS_OP_SUCCESS;
}