bool threadpool_create(struct threadpool * pool, const uint32_t size) { bool ret = false; uint32_t i = 0; struct threadpool_thread *thread = NULL; if (UTILDEBUG_VERIFY((pool != NULL) && (pool->priv == NULL) && (size > 0))) { pool->priv = UTILMEM_CALLOC(struct threadpool_priv, sizeof(struct threadpool_priv), 1); if (pool->priv == NULL) { logger_printf(LOGGER_LEVEL_ERROR, "%s: failed to allocate private memory (%d)\n", __FUNCTION__, errno); } else if (!vector_create(&pool->priv->threads, size, sizeof(struct threadpool_thread))) { threadpool_destroy(pool); } else if (!vector_create(&pool->priv->tasks, 0, sizeof(struct threadpool_task))) { threadpool_destroy(pool); } else if (!cvobj_create(&pool->priv->cv_task)) { threadpool_destroy(pool); } else if (!cvobj_create(&pool->priv->cv_wait)) { threadpool_destroy(pool); } else if (!mutexobj_create(&pool->priv->mtx)) { threadpool_destroy(pool); } else { for (i = 0; i < vector_getsize(&pool->priv->threads); i++) { thread = vector_getval(&pool->priv->threads, i); memset(thread, 0, sizeof(*thread)); if (!threadobj_create(&thread->handle)) { logger_printf(LOGGER_LEVEL_ERROR, "%s: failed to create thread #%u\n", __FUNCTION__, i); } else if (!threadobj_init(&thread->handle, threadpool_taskthread, pool)) { logger_printf(LOGGER_LEVEL_ERROR, "%s: failed to initialize thread #%u\n", __FUNCTION__, i); } } if (i != vector_getsize(&pool->priv->threads)) { logger_printf(LOGGER_LEVEL_ERROR, "%s: failed to create thread pool\n", __FUNCTION__); threadpool_destroy(pool); } else { pool->priv->shutdown = true; ret = true; } } }
static STATUS __taskInit(struct wind_task *task, struct WIND_TCB *tcb, const char *name, int prio, int flags, FUNCPTR entry, int stacksize) { struct threadobj_init_data idata; pthread_mutexattr_t mattr; struct sched_param param; pthread_attr_t thattr; int ret, cprio; ret = check_task_priority(prio, &cprio); if (ret) { errno = ret; return ERROR; } if (name == NULL || *name == '\0') sprintf(task->name, "t%lu", ++anon_tids); else { strncpy(task->name, name, sizeof(task->name)); task->name[sizeof(task->name) - 1] = '\0'; } __RT(pthread_mutexattr_init(&mattr)); __RT(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE)); __RT(pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT)); __RT(pthread_mutexattr_setpshared(&mattr, mutex_scope_attribute)); __RT(pthread_mutex_init(&task->safelock, &mattr)); __RT(pthread_mutexattr_destroy(&mattr)); task->tcb = tcb; tcb->opaque = task; /* * CAUTION: tcb->status in only modified by the owner task * (see suspend/resume hooks), or when such task is guaranteed * not to be running, e.g. in taskActivate(). So we do NOT * take any lock specifically for updating it. However, we * know that a memory barrier will be issued shortly after * such updates because of other locking being in effect, so * we don't explicitely have to provide for it. */ tcb->status = WIND_SUSPEND; tcb->safeCnt = 0; tcb->flags = flags; tcb->entry = entry; pthread_attr_init(&thattr); if (stacksize == 0) stacksize = PTHREAD_STACK_MIN * 4; else if (stacksize < PTHREAD_STACK_MIN) stacksize = PTHREAD_STACK_MIN; memset(¶m, 0, sizeof(param)); param.sched_priority = cprio; pthread_attr_setinheritsched(&thattr, PTHREAD_EXPLICIT_SCHED); pthread_attr_setschedpolicy(&thattr, SCHED_RT); pthread_attr_setschedparam(&thattr, ¶m); pthread_attr_setstacksize(&thattr, stacksize); pthread_attr_setscope(&thattr, thread_scope_attribute); pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); idata.magic = task_magic; idata.wait_hook = task_wait_hook; idata.suspend_hook = task_suspend_hook; idata.finalizer = task_finalizer; idata.priority = cprio; threadobj_init(&task->thobj, &idata); ret = __bt(cluster_addobj(&wind_task_table, task->name, &task->cobj)); if (ret) { warning("duplicate task name: %s", task->name); threadobj_destroy(&task->thobj); __RT(pthread_mutex_destroy(&task->safelock)); errno = S_objLib_OBJ_ID_ERROR; return ERROR; } registry_init_file(&task->fsobj, ®istry_ops); ret = __bt(-__RT(pthread_create(&task->thobj.tid, &thattr, &task_trampoline, task))); pthread_attr_destroy(&thattr); if (ret) { registry_destroy_file(&task->fsobj); cluster_delobj(&wind_task_table, &task->cobj); threadobj_destroy(&task->thobj); __RT(pthread_mutex_destroy(&task->safelock)); errno = ret == -EAGAIN ? S_memLib_NOT_ENOUGH_MEMORY : -ret; return ERROR; } return OK; }