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