blob: ce01458374d3543f72ebfbaeaaaaf3bbba5872f0 [file] [log] [blame]
Chuangcheng Pengd5232982021-07-15 15:49:43 +08001/***************************************************************************
2 * Copyright C 2009 by Amlogic, Inc. All Rights Reserved.
3 */
4/**\file
5 * \brief pthread 调试工具
6 *
7 * \author Gong Ke <ke.gong@amlogic.com>
8 * \date 2010-10-15: create the document
9 ***************************************************************************/
10
11#define AM_DEBUG_LEVEL 5
12
13//#include <am_debug.h>
14#include <am_mem.h>
15#include "pthread.h"
16#include <stdio.h>
17/****************************************************************************
18 * Type define
19 ***************************************************************************/
20
21typedef struct {
22 const char *file;
23 const char *func;
24 int line;
25} AM_ThreadFrame_t;
26
27typedef struct AM_Thread AM_Thread_t;
28struct AM_Thread {
29 AM_Thread_t *prev;
30 AM_Thread_t *next;
31 pthread_t thread;
32 char *name;
33 void* (*entry)(void*);
34 void *arg;
35 AM_ThreadFrame_t *frame;
36 int frame_size;
37 int frame_top;
38};
39
40/****************************************************************************
41 * Static data
42 ***************************************************************************/
43static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
44static pthread_once_t once = PTHREAD_ONCE_INIT;
45static AM_Thread_t *threads = NULL;
46
47/****************************************************************************
48 * Static functions
49 ***************************************************************************/
50
51static void thread_init(void)
52{
53 AM_Thread_t *th;
54
55 th = malloc(sizeof(AM_Thread_t));
56 if(!th)
57 {
58 printf("not enough memory");
59 return;
60 }
61
62 th->thread= pthread_self();
63 th->name = strdup("main");
64 th->entry = NULL;
65 th->arg = NULL;
66 th->prev = NULL;
67 th->next = NULL;
68 th->frame = NULL;
69 th->frame_size = 0;
70 th->frame_top = 0;
71
72 threads = th;
73
74 printf("Register thread \"main\"");
75}
76
77static void thread_remove(AM_Thread_t *th)
78{
79 if(th->prev)
80 th->prev->next = th->next;
81 else
82 threads = th->next;
83 if(th->next)
84 th->next->prev = th->prev;
85
86 if(th->name)
87 free(th->name);
88 if(th->frame)
89 free(th->frame);
90
91 free(th);
92}
93
94static void* thread_entry(void *arg)
95{
96 AM_Thread_t *th = (AM_Thread_t*)arg;
97 void *r;
98
99 pthread_mutex_lock(&lock);
100 th->thread = pthread_self();
101 pthread_mutex_unlock(&lock);
102
103 printf("Register thread \"%s\" %p", th->name, (void*)th->thread);
104
105 r = th->entry(th->arg);
106
107 pthread_mutex_lock(&lock);
108 thread_remove(th);
109 pthread_mutex_unlock(&lock);
110
111 return r;
112}
113
114static AM_Thread_t* thread_get(pthread_t t)
115{
116 AM_Thread_t *th;
117
118 for(th=threads; th; th=th->next)
119 {
120 if(th->thread==t)
121 return th;
122 }
123
124 return NULL;
125}
126
127/****************************************************************************
128 * API functions
129 ***************************************************************************/
130
131/**\brief 创建一个被AM_THREAD管理的线程
132 * \param[out] thread 返回线程句柄
133 * \param[in] attr 线程属性,等于NULL时使用缺省属性
134 * \param start_routine 线程入口函数
135 * \param[in] arg 线程入口函数的参数
136 * \param[in] name 线程名
137 * \return 成功返回0,失败返回错误代码
138 */
139int AM_pthread_create_name(pthread_t *thread,
140 const pthread_attr_t *attr,
141 void* (*start_routine)(void*),
142 void *arg,
143 const char *name)
144{
145 AM_Thread_t *th;
146 int ret;
147
148 pthread_once(&once, thread_init);
149
150 th = malloc(sizeof(AM_Thread_t));
151 if(!th)
152 {
153 printf("not enough memory");
154 return -1;
155 }
156
157 th->thread= -1;
158 th->name = name?strdup(name):NULL;
159 th->entry = start_routine;
160 th->arg = arg;
161 th->prev = NULL;
162 th->frame = NULL;
163 th->frame_size = 0;
164 th->frame_top = 0;
165
166 pthread_mutex_lock(&lock);
167 if(threads)
168 threads->prev = th;
169 th->next = threads;
170 threads = th;
171 pthread_mutex_unlock(&lock);
172
173 ret = pthread_create(thread, attr, thread_entry, th);
174 if(ret)
175 {
176 printf("create thread failed");
177 pthread_mutex_lock(&lock);
178 thread_remove(th);
179 pthread_mutex_unlock(&lock);
180
181 return ret;
182 }
183
184 return 0;
185}
186
187/**\brief 结束当前线程
188 * \param[in] r 返回值
189 */
190void AM_pthread_exit(void *r)
191{
192 AM_Thread_t *th;
193
194 pthread_once(&once, thread_init);
195
196 pthread_mutex_lock(&lock);
197
198 th = thread_get(pthread_self());
199 if(th)
200 thread_remove(th);
201 else
202 printf("thread %p is not registered", (void*)pthread_self());
203
204 pthread_mutex_unlock(&lock);
205
206 pthread_exit(r);
207}
208
209/**\brief 记录当前线程进入一个函数
210 * \param[in] file 文件名
211 * \param[in] func 函数名
212 * \param line 行号
213 * \return 成功返回0,失败返回错误代码
214 */
215int AM_pthread_enter(const char *file, const char *func, int line)
216{
217 AM_Thread_t *th;
218 int ret = 0;
219
220 pthread_once(&once, thread_init);
221
222 pthread_mutex_lock(&lock);
223
224 th = thread_get(pthread_self());
225 if(th)
226 {
227 if((th->frame_top+1)>=th->frame_size)
228 {
229 AM_ThreadFrame_t *f;
230 int size = AM_MAX(th->frame_size*2, 16);
231
232 f = realloc(th->frame, sizeof(AM_ThreadFrame_t)*size);
233 if(!f)
234 {
235 printf("not enough memory");
236 ret = -1;
237 goto error;
238 }
239
240 th->frame = f;
241 th->frame_size = size;
242 }
243 th->frame[th->frame_top].file = file;
244 th->frame[th->frame_top].func = func;
245 th->frame[th->frame_top].line = line;
246 th->frame_top++;
247 }
248 else
249 {
250 printf("thread %p is not registered", (void*)pthread_self());
251 ret = -1;
252 }
253error:
254 pthread_mutex_unlock(&lock);
255 return ret;
256}
257
258/**\brief 记录当前线程离开一个函数
259 * \param[in] file 文件名
260 * \param[in] func 函数名
261 * \param line 行号
262 * \return 成功返回0,失败返回错误代码
263 */
264int AM_pthread_leave(const char *file, const char *func, int line)
265{
266 AM_Thread_t *th;
267
268 pthread_once(&once, thread_init);
269
270 pthread_mutex_lock(&lock);
271
272 th = thread_get(pthread_self());
273 if(th)
274 {
275 if(!th->frame_top)
276 printf("AM_pthread_enter and AM_pthread_leave mismatch");
277 else
278 th->frame_top--;
279 }
280 else
281 {
282 printf("thread %p is not registered", (void*)pthread_self());
283 }
284
285 pthread_mutex_unlock(&lock);
286
287 return 0;
288}
289
290/**\brief 打印当前所有注册线程的状态信息
291 * \return 成功返回0,失败返回错误代码
292 */
293int AM_pthread_dump(void)
294{
295 AM_Thread_t *th;
296 int i, l, n;
297
298 pthread_once(&once, thread_init);
299
300 pthread_mutex_lock(&lock);
301
302 for(th=threads,i=0; th; th=th->next, i++)
303 {
304 if(th->thread==-1)
305 continue;
306
307 fprintf(stdout, "Thread %d (%p:%s)\n", i, (void*)th->thread, th->name?th->name:"");
308 for(l=th->frame_top-1,n=0; l>=0; l--,n++)
309 {
310 AM_ThreadFrame_t *f = &th->frame[l];
311 fprintf(stdout, "\t<%d> %s line %d [%s]\n", n, f->func?f->func:NULL, f->line, f->file?f->file:NULL);
312 }
313 }
314
315 pthread_mutex_unlock(&lock);
316
317 return 0;
318}
319