/*
* Copyright (c) 2020 YuQing <384681@qq.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the Lesser GNU General Public License, version 3
* or later ("LGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "fc_memory.h"
#include "logger.h"
#include "pthread_func.h"
int init_pthread_lock(pthread_mutex_t *pthread_lock)
{
pthread_mutexattr_t mat;
int result;
if ((result=pthread_mutexattr_init(&mat)) != 0) {
logError("file: "__FILE__", line: %d, "
"call pthread_mutexattr_init fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
if ((result=pthread_mutexattr_settype(&mat,
PTHREAD_MUTEX_ERRORCHECK)) != 0)
{
logError("file: "__FILE__", line: %d, "
"call pthread_mutexattr_settype fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
if ((result=pthread_mutex_init(pthread_lock, &mat)) != 0) {
logError("file: "__FILE__", line: %d, "
"call pthread_mutex_init fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
if ((result=pthread_mutexattr_destroy(&mat)) != 0) {
logError("file: "__FILE__", line: %d, "
"call thread_mutexattr_destroy fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
int init_pthread_attr(pthread_attr_t *pattr, const int stack_size)
{
size_t old_stack_size;
size_t new_stack_size;
int result;
if ((result=pthread_attr_init(pattr)) != 0) {
logError("file: "__FILE__", line: %d, "
"call pthread_attr_init fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
if ((result=pthread_attr_getstacksize(pattr, &old_stack_size)) != 0) {
logError("file: "__FILE__", line: %d, "
"call pthread_attr_getstacksize fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
if (stack_size > 0) {
if (old_stack_size != stack_size) {
new_stack_size = stack_size;
} else {
new_stack_size = 0;
}
} else if (old_stack_size < 1 * 1024 * 1024) {
new_stack_size = 1 * 1024 * 1024;
} else {
new_stack_size = 0;
}
if (new_stack_size > 0) {
if ((result=pthread_attr_setstacksize(pattr,
new_stack_size)) != 0)
{
logError("file: "__FILE__", line: %d, "
"call pthread_attr_setstacksize to %d fail, "
"errno: %d, error info: %s", __LINE__,
(int)new_stack_size, result, STRERROR(result));
return result;
}
}
if ((result=pthread_attr_setdetachstate(pattr,
PTHREAD_CREATE_DETACHED)) != 0)
{
logError("file: "__FILE__", line: %d, "
"call pthread_attr_setdetachstate fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
int create_work_threads(int *count, void *(*start_func)(void *),
void **args, pthread_t *tids, const int stack_size)
{
#define FIXED_TID_COUNT 256
int result;
pthread_attr_t thread_attr;
void **current_arg;
pthread_t fixed_tids[FIXED_TID_COUNT];
pthread_t *the_tids;
pthread_t *ptid;
pthread_t *ptid_end;
if ((result=init_pthread_attr(&thread_attr, stack_size)) != 0) {
return result;
}
if (tids != NULL) {
the_tids = tids;
} else {
if (*count <= FIXED_TID_COUNT) {
the_tids = fixed_tids;
} else {
int bytes;
bytes = sizeof(pthread_t) * *count;
the_tids = (pthread_t *)fc_malloc(bytes);
if (the_tids == NULL) {
pthread_attr_destroy(&thread_attr);
return ENOMEM;
}
}
}
result = 0;
ptid_end = the_tids + (*count);
for (ptid=the_tids,current_arg=args; ptidlock)) != 0)
{
logError("file: "__FILE__", line: %d, "
"init_pthread_lock fail, errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
if ((result=pthread_cond_init(&lcp->cond, NULL)) != 0)
{
logError("file: "__FILE__", line: %d, "
"pthread_cond_init fail, "
"errno: %d, error info: %s",
__LINE__, result, STRERROR(result));
return result;
}
return 0;
}
void destroy_pthread_lock_cond_pair(pthread_lock_cond_pair_t *lcp)
{
pthread_cond_destroy(&lcp->cond);
pthread_mutex_destroy(&lcp->lock);
}