Exemplo n.º 1
0
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;
            }
        }
    }
Exemplo n.º 2
0
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(&param, 0, sizeof(param));
	param.sched_priority = cprio;
	pthread_attr_setinheritsched(&thattr, PTHREAD_EXPLICIT_SCHED);
	pthread_attr_setschedpolicy(&thattr, SCHED_RT);
	pthread_attr_setschedparam(&thattr, &param);
	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, &registry_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;
}