[Linux用户空间编程-7]:pThread线程库-线程管理代码示例

作者主页(​​文火冰糖的硅基工坊​​​):​​文火冰糖(王文兵)的博客_文火冰糖的硅基工坊​


目录

​​第1章 头文件​​

​​第2章 设置或获取线程属性​​

​​第3章 绑定Core​​

​​第4章 创建线程​​


第1章 头文件

#ifndef _MY_THREAD_H_
#define _MY_THREAD_H_

#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>

/*** Definition ***/
#define APP_THREAD_CNT 32

#define THREAD_PRI_DEMO 60

#define true 1
#define false 0

typedef enum
{
COORE_ALL=-1,
CORE0=0,
CORE1,
CORE2,
CORE3,
CORE4,
CORE5,
CORE6,
CORE7,
CORE8,
CORE9,
CORE10,
} CORE_ID;

/*** Data Structure ***/
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;

typedef void * (* ThreadFunction_t) (void*);

typedef struct thread_queue_info_struct_t
{
bool valid;
const char *pName;
ThreadFunction_t entry;
UINT32 policy;
UINT32 priority;
CORE_ID core;
} THREAD_QUEUE_INFO;

/*** Funtion Call ***/
// Demo thread
void *demo_thread(void *);
void * demo_dumy(void *);

// Thread attributes
int GetSelfThreadSchedParam(int *pPolicy, int *pPriority);
int SetSelfThreadSchedParam(int policy, int priority);
void DisplayPthreadAttribute(pthread_t *pTid, pthread_attr_t *attr);
int SetThreadPriority(pthread_attr_t *pAttr, int priority);


//Bind Core
int BindTidThreadToCore(pthread_t tid, int core_id);
int BindCurrentThreadToCore(int core_id);
void DisplaySelfThreadCores(void);

//Create Thread
int CreateNormalThread(pthread_t *pTid, ThreadFunction_t function, int priority);
int CreateCustomizedThread(pthread_t *pTid, const char *pName, ThreadFunction_t pThreadEntry, UINT32 policy, UINT32 priority, CORE_ID core);
void CreateBatchThreads(void);

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _OSA_THREAD_H_ */

第2章 设置或获取线程属性

int GetSelfThreadSchedParam(int *pPolicy, int *pPriority)
{
struct sched_param param;
int local_policy;

pthread_t tid = pthread_self();

if(pthread_getschedparam(tid, &local_policy, &param))
{
printf("pthread_getschedparam failed, tid=%u\n", (unsigned int)tid);
return -1;
}
else
{
*pPolicy = local_policy;
*pPriority = param.sched_priority;
printf("pThread [%u] get policy[%d] priority[%d]\n", (unsigned int) tid, local_policy, param.sched_priority);
return 0;
}
}


int SetSelfThreadSchedParam(int policy, int priority)
{
struct sched_param param;
int local_policy;

pthread_t tid = pthread_self();

if(pthread_getschedparam(tid, &local_policy, &param))
{
printf("pthread_getschedparam failed, tid=%ld\n", tid);
return -1;
}
printf("pThread [%lu] get policy[%d] priority[%d] before set\n", tid, local_policy, param.sched_priority);

param.sched_priority = priority;
local_policy = policy;
if(pthread_setschedparam(tid, local_policy, &param))
{
printf("pthread_setschedparam failed, tid=%lu\n", tid);
return -1;
}

if(pthread_getschedparam(tid, &local_policy, &param))
{
printf("pthread_getschedparam failed, tid=%ld\n", tid);
return -1;
}
printf("pThread [%lu] get policy[%d] priority[%d] after set\n", tid, local_policy, param.sched_priority);
return 0;
}


void DisplayPthreadAttribute(pthread_t *pTid, pthread_attr_t *attr)
{
int status, value;
size_t size;
void *stkaddr;
struct sched_param sp;

printf("Thread Attributes for tid=%u:\n", (unsigned int)(*pTid));
//get the detachstate
status = pthread_attr_getdetachstate(attr, &value);
if (status != 0)
{
printf("pthread_attr_getdetachstate error=%d!\n", status);
}

printf("\tDetach state = %s\n",
(value == PTHREAD_CREATE_DETACHED) ? "PTHREAD_CREATE_DETACHED" :
(value == PTHREAD_CREATE_JOINABLE) ? "PTHREAD_CREATE_JOINABLE" :
"???");

//get the scope
status = pthread_attr_getscope(attr, &value);
if (status!= 0)
{
printf("pthread_attr_getscope error=%d!\n", status);
}

printf("\tScope = %s\n",
(value == PTHREAD_SCOPE_SYSTEM) ? "PTHREAD_SCOPE_SYSTEM" :
(value == PTHREAD_SCOPE_PROCESS) ? "PTHREAD_SCOPE_PROCESS" :
"???");

//get the inheritsched
status = pthread_attr_getinheritsched(attr, &value);
if (status != 0)
{
printf("pthread_attr_getinheritsched error=%d!\n", status);
}
printf("\tInherit scheduler = %s\n",
(value == PTHREAD_INHERIT_SCHED) ? "PTHREAD_INHERIT_SCHED" :
(value == PTHREAD_EXPLICIT_SCHED) ? "PTHREAD_EXPLICIT_SCHED" :
"???");

// get the policy
status= pthread_attr_getschedpolicy(attr, &value);
if (status != 0)
{
printf("pthread_attr_getschedpolicy error=%d!\n", status);
}
printf("\tScheduling policy = %s\n",
(value== SCHED_OTHER) ? "SCHED_OTHER" :
(value== SCHED_FIFO) ? "SCHED_FIFO" :
(value == SCHED_RR) ? "SCHED_RR" :
"???");

//get the schedparam: sched_priority
status = pthread_attr_getschedparam(attr, &sp);
if (status != 0)
{
printf("pthread_attr_getschedparam error=%d!\n", status);
}
printf("\tScheduling priority = %d\n", sp.sched_priority);

//get the guardsize of stack
status= pthread_attr_getguardsize(attr, &size);
if (status != 0)
{
printf("pthread_attr_getguardsize error=%d!\n", status);
}
printf("\tGuard size = %lu bytes\n", size);

//get the stack
status= pthread_attr_getstack(attr, &stkaddr, &size);
if (status != 0)
{
printf("pthread_attr_getstack error=%d!\n", status);
}
printf("\tStack address = %p\n", stkaddr);
printf("\tStack size = %lu bytes\n", size);
}

int SetThreadPriority(pthread_attr_t *pAttr, int priority)
{
struct sched_param param;
int policy;
int min, max; // thread priority

//Get the current schedparams of scheduler
if (pthread_attr_getschedparam(pAttr, &param))
{
printf("pthread_attr_getschedparam failed\n");
return -1;
}

/* Get current policy of scheduler */
if (pthread_attr_getschedpolicy(pAttr, &policy))
{
printf("pthread_attr_getschedpolicy failed\n");
return -1;
}

// get max priority based on policy
max = sched_get_priority_max(policy);

if (priority > max)
{
printf("priority(%d) is higher than max(%d)\n", priority, max);
priority = max;
}
// min priority
min = sched_get_priority_min(policy);
if (priority < min)
{
printf("priority(%d) is lower than min(%d)\n", priority, min);
priority = min;
}

// set priority of scheduler
param.sched_priority = priority;
if (pthread_attr_setschedparam(pAttr, &param))
{
printf("pthread_attr_setschedparam failed\n");
return -1;
}
//printf("pthread_attr_setschedparam successfully: priority=%d for policy=%d\n", priority, policy);

return 0; // success
}

第3章 绑定Core

int BindTidThreadToCore(pthread_t tid, int core_id)
{
int ret;
int num_cores = sysconf(_SC_NPROCESSORS_ONLN);

cpu_set_t cpuset;

//check the numbers of valid cores
if ((0 > core_id) || (num_cores <= core_id))
{
return EINVAL;
}

//prepare the cpu_set_t
CPU_ZERO(&cpuset);
CPU_SET(core_id, &cpuset);

//bind tid to cpu set
ret = pthread_setaffinity_np(tid, sizeof(cpu_set_t), &cpuset);

printf("Bind Thread %lu to core Core %d, num_cores=%d , status=%d\n", tid, core_id, num_cores, ret);
return ret;
}

int BindCurrentThreadToCore(int core_id)
{
int ret;
pthread_t current_thread = pthread_self();

ret = BindTidThreadToCore(current_thread, core_id);

return ret;
}


void DisplaySelfThreadCores(void)
{
int status;
cpu_set_t cpuset;
pthread_t current_thread = pthread_self();

CPU_ZERO(&cpuset);

status = pthread_getaffinity_np(current_thread, sizeof(cpuset), & cpuset) ;
if (status!= 0)
{
printf("sched_getaffinity error=%d!\n", status);
}

int cpus = sysconf(_SC_NPROCESSORS_CONF);
char sbuf[128];
char *ptr = sbuf;
memset(sbuf, sizeof(sbuf), 0);

for(int i = 0; i < cpus; i++)
{
if (CPU_ISSET(i, &cpuset))
{
ptr +=sprintf(ptr, " %d,", i);
}
}
printf("The thread %lu run on processor: %s\n", current_thread, sbuf);
}

第4章 创建线程

int CreateCustomizedThread(pthread_t *pTid, const char *pName, ThreadFunction_t pThreadEntry, UINT32 policy, UINT32 priority, CORE_ID core)
{
pthread_attr_t attr;
pthread_t tid;
struct sched_param param;
int local_policy;
int ret = 0;

//make the intial attribute for thread
ret = pthread_attr_init(&attr);
if(ret != 0)
{
printf("pthread_attr_init\n");
return ret;
}

//set detach state of thread
ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if(ret != 0)
{
printf("pthread_attr_setdetachstate fail\n");
return ret;
}

//set policy and priority of thread
if((policy == SCHED_RR) || (policy == SCHED_RR))
{
ret = pthread_attr_setschedpolicy(&attr, policy);
if(ret != 0)
{
printf("pthread_attr_setschedpolicy fail\n");
return ret;
}

ret = SetThreadPriority(&attr, priority);
if(ret != 0)
{
printf("SetThreadPriority fail\n");
return ret;
}
}

//create thread
ret = pthread_create(&tid, &attr, pThreadEntry, NULL);
if(ret != 0)
{
printf("pthread_create fail\n");
return ret;
}

//save tid of thread
memcpy(pTid, &tid, sizeof(pthread_t));

//DisplayPthreadAttribute(&tid, &attr);

//set the thread name
if(pName != NULL)
{
printf("set pthread %lu with name %s\n", tid, pName);

//must be self?
ret = pthread_setname_np(tid, pName);
if(ret !=0)
{
printf("pthread_setname_np fail\n");
return ret;
}
}

//bind core
if(core >= 0)
{
ret = BindTidThreadToCore(tid, core);
if(ret != 0)
{
printf("BindTidThreadToCore fail\n");
return ret;
}
}

return ret;
}

作者主页(​​文火冰糖的硅基工坊​​​):​​文火冰糖(王文兵)的博客_文火冰糖的硅基工坊​