fix prevent violation
[framework/system/dynamic-analysis-probe.git] / probe_thread / libdathread.c
1 /*
2  *  DA probe
3  *
4  * Copyright 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Woojin Jung <woojin2.jung@samsung.com>
9  * Jaewon Lim <jaewon81.lim@samsung.com>
10  * Juyoung Kim <j0.kim@samsung.com>
11  *
12  * This library is free software; you can redistribute it and/or modify it under
13  * the terms of the GNU Lesser General Public License as published by the
14  * Free Software Foundation; either version 2.1 of the License, or (at your option)
15  * any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
18  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
20  * License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public License
23  * along with this library; if not, write to the Free Software Foundation, Inc., 51
24  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  *
29  */
30
31 #include <pthread.h>
32 #include <errno.h>
33 #include "daprobe.h"
34 #include "probeinfo.h"
35 #include "dahelper.h"
36 #include "da_thread.h"
37
38 typedef struct thread_routine_call_t {
39         void *(*thread_routine)(void *);
40         void *argument;
41 } thread_routine_call;
42
43 static enum DaOptions _sopt = OPT_THREAD;
44
45 // called when pthread_exit, pthread_cancel is called
46 void _da_cleanup_handler(void *data)
47 {
48         pthread_t pSelf;
49
50         DECLARE_COMMON_VARIABLE;
51         INIT_LOG;
52         
53         PRE_UNCONDITIONAL_BLOCK_BEGIN();
54         APPEND_LOG_BASIC(LC_THREAD);
55         // input,ret,PCAddr,errno,InternalCall,CallerPCAddr
56         log.length += sprintf(log.data + log.length, "`,`,`,0`,0`,1`,0");
57         pSelf = pthread_self();
58         log.length += sprintf(log.data + log.length, "`,%lu`,`,%d`,%d",
59                         pSelf, THREAD_PTHREAD, THREAD_API_INTERNAL_STOP);
60         APPEND_LOG_NULL_CALLSTACK();
61         printLog(&log, MSG_LOG);
62         PRE_UNCONDITIONAL_BLOCK_END();
63
64         return;
65 }
66
67 void *_da_ThreadProc(void *params)
68 {
69         void *ret;
70         thread_routine_call *ptrc;
71         ptrc = (thread_routine_call *) params;
72         pthread_t pSelf;
73
74         DECLARE_COMMON_VARIABLE;
75
76         // send INTERNAL_START log
77         INIT_LOG;
78
79         PRE_UNCONDITIONAL_BLOCK_BEGIN();
80         APPEND_LOG_BASIC(LC_THREAD);
81         // input,ret,PCAddr,errno,InternalCall,CallerPCAddr
82         log.length += sprintf(log.data + log.length, "`,`,`,0`,0`,1`,0");
83         pSelf = pthread_self();
84         log.length += sprintf(log.data + log.length, "`,%lu`,`,%d`,%d",
85                         pSelf, THREAD_PTHREAD, THREAD_API_INTERNAL_START);
86         APPEND_LOG_NULL_CALLSTACK();
87         printLog(&log, MSG_LOG);
88         PRE_UNCONDITIONAL_BLOCK_END();
89
90         pthread_cleanup_push(_da_cleanup_handler, NULL);
91         // call user-defined thread routine
92         ret = ptrc->thread_routine(ptrc->argument);
93         pthread_cleanup_pop(0);
94
95         // send INTERNAL_STOP log
96         INIT_LOG;
97
98         PRE_UNCONDITIONAL_BLOCK_BEGIN();
99         APPEND_LOG_BASIC(LC_THREAD);
100         // input,ret,PCAddr,errno,InternalCall,CallerPCAddr
101         log.length += sprintf(log.data + log.length, "`,`,`,0`,0`,1`,0");
102         pSelf = pthread_self();
103         log.length += sprintf(log.data + log.length, "`,%lu`,`,%d`,%d",
104                         pSelf, THREAD_PTHREAD, THREAD_API_INTERNAL_STOP);
105         APPEND_LOG_NULL_CALLSTACK();
106         printLog(&log, MSG_LOG);
107         PRE_UNCONDITIONAL_BLOCK_END();
108         
109         free(ptrc);
110         return ret;
111 }
112
113 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, 
114                 void *(*start_routine) (void*), void *arg)
115 {
116         static int (*pthread_createp)(pthread_t *thread,
117                         const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
118
119         BEFORE_ORIGINAL_THREAD(pthread_create, LIBPTHREAD);
120
121         if(blockresult)
122         {
123                 probeBlockStart();      
124                 thread_routine_call *ptrc = 
125                         (thread_routine_call *) malloc(sizeof(thread_routine_call));
126                 ptrc->thread_routine = start_routine;
127                 ptrc->argument = arg;
128                 probeBlockEnd();
129
130                 ret = pthread_createp(thread, attr, _da_ThreadProc, (void *) ptrc);
131         }
132         else // when pthread_create is called inside probe so (ex. custom chart, sampling thread)
133         {
134                 ret = pthread_createp(thread, attr, start_routine, arg);
135         }
136
137         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, *thread, THREAD_API_START, 
138                         "%p,%p,%p,%p", thread, attr, start_routine, arg);
139
140         return ret;
141 }
142
143 int pthread_join(pthread_t thread, void **retval)
144 {
145         static int (*pthread_joinp)(pthread_t thread, void **retval);
146
147         DECLARE_VARIABLE_STANDARD;
148         GET_REAL_FUNC(pthread_join, LIBPTHREAD);
149
150         PRE_PROBEBLOCK_BEGIN();
151         // send WAIT_START log
152         INIT_LOG;
153         APPEND_LOG_BASIC(LC_THREAD);
154         APPEND_LOG_INPUT("%lu,%p", thread, retval);
155         //ret,PCAddr,errno,InternalCall
156         log.length += sprintf(log.data + log.length, "`,`,0`,0`,%d", blockresult);
157         APPEND_LOG_CALLER();
158         log.length += sprintf(log.data + log.length, "`,%lu`,`,%d`,%d", thread, 
159                         THREAD_PTHREAD, THREAD_API_WAIT_START);
160         APPEND_LOG_NULL_CALLSTACK();
161         printLog(&log, MSG_LOG);
162         PRE_PROBEBLOCK_END();
163
164         ret = pthread_joinp(thread, retval);
165
166         // send WAIT_END log
167         newerrno = errno;
168         if(postBlockBegin(blockresult)) {
169                 setProbePoint(&probeInfo);
170                 INIT_LOG;
171                 APPEND_LOG_BASIC(LC_THREAD);
172                 APPEND_LOG_INPUT("%lu,%p", thread, retval);
173                 APPEND_LOG_RESULT(VT_INT, ret);
174                 APPEND_LOG_CALLER();
175
176                 POST_PROBEBLOCK_MIDDLE_THREAD(thread, THREAD_API_WAIT_END);
177                 POST_PROBEBLOCK_CALLSTACK();
178                 printLog(&log, MSG_LOG);
179                 postBlockEnd();
180         }
181         
182         return ret;     
183 }
184
185 void pthread_exit(void *retval)
186 {
187         pthread_t pSelf;
188         static void (*pthread_exitp)(void *retval) __attribute__((noreturn));
189
190         DECLARE_VARIABLE_STANDARD;
191         GET_REAL_FUNC(pthread_exit, LIBPTHREAD);
192
193         PRE_PROBEBLOCK_BEGIN();
194         newerrno = 0;
195         INIT_LOG;
196         APPEND_LOG_BASIC(LC_THREAD);
197         APPEND_LOG_INPUT("%p", retval);
198         //ret,PCAddr,errno,InternalCall
199         log.length += sprintf(log.data + log.length, "`,`,0`,0`,%d", blockresult);
200         APPEND_LOG_CALLER();
201         pSelf = pthread_self();
202         log.length += sprintf(log.data + log.length, "`,%lu`,`,%d`,%d",
203                         pSelf, THREAD_PTHREAD, THREAD_API_EXIT);
204         APPEND_LOG_NULL_CALLSTACK();
205         printLog(&log, MSG_LOG);
206         PRE_PROBEBLOCK_END();
207
208         pthread_exitp(retval);
209 }
210
211 int pthread_cancel(pthread_t thread)
212 {
213         static int (*pthread_cancelp)(pthread_t thread);
214
215         BEFORE_ORIGINAL_THREAD(pthread_cancel, LIBPTHREAD);
216
217         ret = pthread_cancelp(thread);
218         
219         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_STOP, "%lu", thread);
220
221         return ret;
222 }
223
224 int pthread_detach(pthread_t thread)
225 {
226         static int (*pthread_detachp)(pthread_t thread);
227
228         BEFORE_ORIGINAL_THREAD(pthread_detach, LIBPTHREAD);
229
230         ret = pthread_detachp(thread);
231         
232         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, "%lu", thread);
233
234         return ret;
235 }
236
237 pthread_t pthread_self(void)
238 {
239         pthread_t ret_pthr;
240         static pthread_t (*pthread_selfp)(void);
241
242         BEFORE_ORIGINAL_THREAD(pthread_self, LIBPTHREAD);
243
244         ret_pthr = pthread_selfp();
245         
246         newerrno = errno;
247         if(postBlockBegin(blockresult)) {
248                 INIT_LOG;
249                 APPEND_LOG_BASIC(LC_THREAD);
250                 log.length += sprintf(log.data + log.length, "`,");
251                 APPEND_LOG_RESULT(VT_ULONG, ret_pthr);
252                 APPEND_LOG_CALLER();
253
254                 POST_PROBEBLOCK_MIDDLE_THREAD(ret_pthr, THREAD_API_OTHER);
255                 POST_PROBEBLOCK_CALLSTACK();
256                 printLog(&log, MSG_LOG);
257                 postBlockEnd();
258         }
259
260         return ret_pthr;
261 }
262
263 int pthread_equal(pthread_t t1, pthread_t t2)
264 {
265         static int (*pthread_equalp)(pthread_t t1, pthread_t t2);
266
267         BEFORE_ORIGINAL_THREAD(pthread_equal, LIBPTHREAD);
268
269         ret = pthread_equalp(t1, t2);
270         
271         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, t1, THREAD_API_OTHER, "%lu,%lu", t1, t2);
272
273         return ret;
274 }
275
276 int pthread_setcancelstate(int state, int *oldstate)
277 {
278         pthread_t pSelf;
279         static int (*pthread_setcancelstatep)(int state, int *oldstate);
280
281         BEFORE_ORIGINAL_THREAD(pthread_setcancelstate, LIBPTHREAD);
282
283         pSelf = pthread_self();
284         ret = pthread_setcancelstatep(state, oldstate);
285
286         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, pSelf, THREAD_API_OTHER, 
287                         "%d,%p", state, oldstate); 
288
289         return ret;
290 }
291
292 int pthread_setcanceltype(int type, int *oldtype)
293 {
294         pthread_t pSelf;
295         static int (*pthread_setcanceltypep)(int type, int *oldtype);
296
297         BEFORE_ORIGINAL_THREAD(pthread_setcanceltype, LIBPTHREAD);
298
299         pSelf = pthread_self();
300         ret = pthread_setcanceltypep(type, oldtype);
301
302         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, pSelf, THREAD_API_OTHER, 
303                         "%d,%p", type, oldtype); 
304
305         return ret;
306 }
307
308 int pthread_attr_init(pthread_attr_t *attr)
309 {
310         pthread_t thread = 0;
311         static int (*pthread_attr_initp)(pthread_attr_t *attr);
312
313         BEFORE_ORIGINAL_THREAD(pthread_attr_init, LIBPTHREAD);
314
315         ret = pthread_attr_initp(attr);
316
317         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, "%p", attr);
318
319         return ret;
320 }
321
322 int pthread_attr_destroy(pthread_attr_t *attr) 
323 {
324         pthread_t thread = 0;
325         static int (*pthread_attr_destroyp)(pthread_attr_t *attr);
326
327         BEFORE_ORIGINAL_THREAD(pthread_attr_destroy, LIBPTHREAD);
328
329         ret = pthread_attr_destroyp(attr);
330
331         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, "%p", attr);
332
333         return ret;
334 }
335
336 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
337 {
338         pthread_t thread = 0;
339         static int (*pthread_attr_getdetachstatep)(const pthread_attr_t *attr,
340                         int *detachstate);
341
342         BEFORE_ORIGINAL_THREAD(pthread_attr_getdetachstate, LIBPTHREAD);
343
344         ret = pthread_attr_getdetachstatep(attr, detachstate);
345
346         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
347                         "%p,%p", attr, detachstate);
348
349         return ret;
350 }
351
352 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
353 {
354         pthread_t thread = 0;
355         static int (*pthread_attr_setdetachstatep)(pthread_attr_t *attr, 
356                         int detachstate);
357
358         BEFORE_ORIGINAL_THREAD(pthread_attr_setdetachstate, LIBPTHREAD);
359
360         ret = pthread_attr_setdetachstatep(attr, detachstate);
361
362         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
363                         "%p,%d", attr, detachstate);
364
365         return ret;
366 }
367
368 int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
369 {
370         pthread_t thread = 0;
371         static int (*pthread_attr_getstacksizep)(const pthread_attr_t *attr,
372                         size_t *stacksize);
373
374         BEFORE_ORIGINAL_THREAD(pthread_attr_getstacksize, LIBPTHREAD);
375
376         ret = pthread_attr_getstacksizep(attr, stacksize);
377
378         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
379                         "%p,%p", attr, stacksize);
380
381         return ret;
382 }
383
384 int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
385 {
386         pthread_t thread = 0;
387         static int (*pthread_attr_setstacksizep)(pthread_attr_t *attr, 
388                         size_t stacksize);
389
390         BEFORE_ORIGINAL_THREAD(pthread_attr_setstacksize, LIBPTHREAD);
391
392         ret = pthread_attr_setstacksizep(attr, stacksize);
393
394         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
395                         "%p,%u", attr, stacksize);
396
397         return ret;
398 }
399
400 int pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
401 {
402         pthread_t thread = 0;
403         static int (*pthread_attr_getstackaddrp)(const pthread_attr_t *attr,
404                         void **stackaddr);
405
406         BEFORE_ORIGINAL_THREAD(pthread_attr_getstackaddr, LIBPTHREAD);
407
408         ret = pthread_attr_getstackaddrp(attr, stackaddr);
409
410         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
411                         "%p,%p", attr, stackaddr);
412
413         return ret;
414 }
415
416 int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
417 {
418         pthread_t thread = 0;
419         static int (*pthread_attr_setstackaddrp)(pthread_attr_t *attr, 
420                         void *stackaddr);
421
422         BEFORE_ORIGINAL_THREAD(pthread_attr_setstackaddr, LIBPTHREAD);
423
424         ret = pthread_attr_setstackaddrp(attr, stackaddr);
425
426         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
427                         "%p,%p", attr, stackaddr);
428
429         return ret;
430 }
431
432 int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched)
433 {
434         pthread_t thread = 0;
435         static int (*pthread_attr_getinheritschedp)(const pthread_attr_t *attr,
436                         int *inheritsched);
437
438         BEFORE_ORIGINAL_THREAD(pthread_attr_getinheritsched, LIBPTHREAD);
439
440         ret = pthread_attr_getinheritschedp(attr, inheritsched);
441
442         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
443                         "%p,%p", attr, inheritsched);
444
445         return ret;
446 }
447
448 int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched)
449 {
450         pthread_t thread = 0;
451         static int (*pthread_attr_setinheritschedp)(pthread_attr_t *attr, 
452                         int inheritsched);
453
454         BEFORE_ORIGINAL_THREAD(pthread_attr_setinheritsched, LIBPTHREAD);
455
456         ret = pthread_attr_setinheritschedp(attr, inheritsched);
457
458         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
459                         "%p,%d", attr, inheritsched);
460
461         return ret;
462 }
463
464 int pthread_attr_getschedparam(const pthread_attr_t *attr,
465                 struct sched_param *param)
466 {
467         pthread_t thread = 0;
468         static int (*pthread_attr_getschedparamp)(const pthread_attr_t *attr,
469                         struct sched_param *param);
470
471         BEFORE_ORIGINAL_THREAD(pthread_attr_getschedparam, LIBPTHREAD);
472
473         ret = pthread_attr_getschedparamp(attr, param);
474
475         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
476                         "%p,%p", attr, param);
477
478         return ret;
479 }
480
481 int pthread_attr_setschedparam(pthread_attr_t *attr, 
482                 const struct sched_param *param)
483 {
484         pthread_t thread = 0;
485         static int (*pthread_attr_setschedparamp)(pthread_attr_t *attr,
486                         const struct sched_param *param);
487
488         BEFORE_ORIGINAL_THREAD(pthread_attr_setschedparam, LIBPTHREAD);
489
490         ret = pthread_attr_setschedparamp(attr, param);
491
492         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
493                         "%p,%p", attr, param);
494
495         return ret;
496 }
497
498 int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
499 {
500         pthread_t thread = 0;
501         static int (*pthread_attr_getschedpolicyp)(const pthread_attr_t *attr,
502                         int *policy);
503
504         BEFORE_ORIGINAL_THREAD(pthread_attr_getschedpolicy, LIBPTHREAD);
505
506         ret = pthread_attr_getschedpolicyp(attr, policy);
507
508         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
509                         "%p,%p", attr, policy);
510
511         return ret;
512 }
513
514 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
515 {
516         pthread_t thread = 0;
517         static int (*pthread_attr_setschedpolicyp)(pthread_attr_t *attr, 
518                         int policy);
519
520         BEFORE_ORIGINAL_THREAD(pthread_attr_setschedpolicy, LIBPTHREAD);
521
522         ret = pthread_attr_setschedpolicyp(attr, policy);
523
524         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
525                         "%p,%d", attr, policy);
526
527         return ret;
528 }
529
530 int pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
531 {
532         pthread_t thread = 0;
533         static int (*pthread_attr_getguardsizep)(const pthread_attr_t *attr,
534                         size_t *guardsize);
535
536         BEFORE_ORIGINAL_THREAD(pthread_attr_getguardsize, LIBPTHREAD);
537
538         ret = pthread_attr_getguardsizep(attr, guardsize);
539
540         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
541                         "%p,%p", attr, guardsize);
542
543         return ret;
544 }
545
546 int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
547 {
548         pthread_t thread = 0;
549         static int (*pthread_attr_setguardsizep)(pthread_attr_t *attr, 
550                         size_t guardsize);
551
552         BEFORE_ORIGINAL_THREAD(pthread_attr_setguardsize, LIBPTHREAD);
553
554         ret = pthread_attr_setguardsizep(attr, guardsize);
555
556         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
557                         "%p,%u", attr, guardsize);
558
559         return ret;
560 }
561
562 int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope)
563 {
564         pthread_t thread = 0;
565         static int (*pthread_attr_getscopep)(const pthread_attr_t *attr,
566                         int *contentionscope);
567
568         BEFORE_ORIGINAL_THREAD(pthread_attr_getscope, LIBPTHREAD);
569
570         ret = pthread_attr_getscopep(attr, contentionscope);
571
572         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
573                         "%p,%p", attr, contentionscope);
574
575         return ret;
576 }
577
578 int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
579 {
580         pthread_t thread = 0;
581         static int (*pthread_attr_setscopep)(pthread_attr_t *attr, 
582                         int contentionscope);
583
584         BEFORE_ORIGINAL_THREAD(pthread_attr_setscope, LIBPTHREAD);
585
586         ret = pthread_attr_setscopep(attr, contentionscope);
587
588         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
589                         "%p,%d", attr, contentionscope);
590
591         return ret;
592 }
593
594 int pthread_attr_getstack(const pthread_attr_t *attr, 
595                 void **stackaddr, size_t *stacksize)
596 {
597         pthread_t thread = 0;
598         static int (*pthread_attr_getstackp)(const pthread_attr_t *attr,
599                         void **stackaddr, size_t *stacksize);
600
601         BEFORE_ORIGINAL_THREAD(pthread_attr_getstack, LIBPTHREAD);
602
603         ret = pthread_attr_getstackp(attr, stackaddr, stacksize);
604
605         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
606                         "%p,%p,%p", attr, stackaddr, stacksize);
607
608         return ret;
609 }
610
611 int pthread_attr_setstack(pthread_attr_t *attr,
612                 void *stackaddr, size_t stacksize)
613 {
614         pthread_t thread = 0;
615         static int (*pthread_attr_setstackp)(pthread_attr_t *attr,
616                         void *stackaddr, size_t stacksize);
617
618         BEFORE_ORIGINAL_THREAD(pthread_attr_setstack, LIBPTHREAD);
619
620         ret = pthread_attr_setstackp(attr, stackaddr, stacksize);
621
622         AFTER_ORIGINAL_THREAD_RET(VT_INT, ret, thread, THREAD_API_OTHER, 
623                         "%p,%p,%u", attr, stackaddr, stacksize);
624
625         return ret;
626 }
627
628 /*
629 void pthread_testcancel(void);
630
631 int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
632 int pthread_key_delete(pthread_key_t key);
633
634 int pthread_getconcurrency(void);
635 int pthread_setconcurrency(int new_level);
636 int pthread_getcpuclockid(pthread_t thread_id, clockid_t *clock_id);
637 int pthread_getschedparam(pthread_t thread, int *policy,
638                 struct sched_param *param);
639 int pthread_setschedparam(pthread_t thread, int policy,
640                 const struct sched_param *param);
641 int pthread_setschedprio(pthread_t thread, int prio);
642 void *pthread_getspecific(pthread_key_t key);
643 int pthread_setspecific(pthread_key_t key, const void *value);
644
645 int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
646
647 int pthread_atfork(void (*prepare)(void), void (*parent)(void),
648                 void (*child)(void));
649 */
650