1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 #include <config.h>
30
31 #include <pthread.h>
32 #include <signal.h>
33 #include <sched.h>
34
35 #include <sys/time.h>
36 #include <sys/resource.h>
37
38 #include <direct/debug.h>
39 #include <direct/list.h>
40 #include <direct/mem.h>
41 #include <direct/messages.h>
42 #include <direct/signals.h>
43 #include <direct/system.h>
44 #include <direct/thread.h>
45 #include <direct/util.h>
46
47 D_DEBUG_DOMAIN( Direct_Thread, "Direct/Thread", "Thread management" );
48 D_DEBUG_DOMAIN( Direct_ThreadInit, "Direct/Thread/Init", "Thread initialization" );
49
50
51 /* FIXME: DIRECT_THREAD_WAIT_INIT is required, but should be optional. */
52 #define DIRECT_THREAD_WAIT_INIT
53
54
55 struct __D_DirectThread {
56 int magic;
57
58 pthread_t thread; /* The pthread thread identifier. */
59 pid_t tid;
60
61 char *name;
62
63 DirectThreadType type; /* The thread's type, e.g. input thread. */
64 DirectThreadMainFunc main; /* The thread's main routine (or entry point). */
65 void *arg; /* Custom argument passed to the main routine. */
66
67 bool canceled; /* Set when direct_thread_cancel() is called. */
68 bool joining; /* Set when direct_thread_join() is called. */
69 bool joined; /* Set when direct_thread_join() has finished. */
70 bool detached; /* Set when direct_thread_detach() is called. */
71 bool terminated; /* Set when direct_thread_terminate() is called. */
72
73 #ifdef DIRECT_THREAD_WAIT_INIT
74 bool init; /* Set to true before calling the main routine. */
75 #endif
76
77 pthread_mutex_t lock;
78 pthread_cond_t cond;
79
80 unsigned int counter;
81 };
82
83 struct __D_DirectThreadInitHandler {
84 DirectLink link;
85
86 int magic;
87
88 DirectThreadInitFunc func;
89 void *arg;
90 };
91
92 /******************************************************************************/
93
94 /*
95 * Wrapper around pthread's main routine to pass additional arguments
96 * and setup things like signal masks and scheduling priorities.
97 */
98 static void *direct_thread_main( void *arg );
99
100 /******************************************************************************/
101
102 static pthread_mutex_t handler_lock = PTHREAD_MUTEX_INITIALIZER;
103 static DirectLink *handlers = NULL;
104
105 /******************************************************************************/
106
107 DirectThreadInitHandler *
direct_thread_add_init_handler(DirectThreadInitFunc func,void * arg)108 direct_thread_add_init_handler( DirectThreadInitFunc func,
109 void *arg )
110 {
111 DirectThreadInitHandler *handler;
112
113 handler = D_CALLOC( 1, sizeof(DirectThreadInitHandler) );
114 if (!handler) {
115 D_WARN( "out of memory" );
116 return NULL;
117 }
118
119 handler->func = func;
120 handler->arg = arg;
121
122 D_MAGIC_SET( handler, DirectThreadInitHandler );
123
124 pthread_mutex_lock( &handler_lock );
125
126 direct_list_append( &handlers, &handler->link );
127
128 pthread_mutex_unlock( &handler_lock );
129
130 return handler;
131 }
132
133 void
direct_thread_remove_init_handler(DirectThreadInitHandler * handler)134 direct_thread_remove_init_handler( DirectThreadInitHandler *handler )
135 {
136 D_MAGIC_ASSERT( handler, DirectThreadInitHandler );
137
138 pthread_mutex_lock( &handler_lock );
139
140 direct_list_remove( &handlers, &handler->link );
141
142 pthread_mutex_unlock( &handler_lock );
143
144 D_MAGIC_CLEAR( handler );
145
146 D_FREE( handler );
147 }
148
149 /******************************************************************************/
150
151 static pthread_mutex_t key_lock = PTHREAD_MUTEX_INITIALIZER;
152 static pthread_key_t thread_key = -1;
153
154 /******************************************************************************/
155
156 DirectThread *
direct_thread_create(DirectThreadType thread_type,DirectThreadMainFunc thread_main,void * arg,const char * name)157 direct_thread_create( DirectThreadType thread_type,
158 DirectThreadMainFunc thread_main,
159 void *arg,
160 const char *name )
161 {
162 DirectThread *thread;
163 pthread_attr_t attr;
164 struct sched_param param;
165 int policy;
166 int priority;
167 size_t stack_size;
168
169 D_ASSERT( thread_main != NULL );
170 D_ASSERT( name != NULL );
171
172 D_DEBUG_AT( Direct_Thread, "%s( %s, %p(%p), '%s' )\n", __FUNCTION__,
173 direct_thread_type_name(thread_type), thread_main, arg, name );
174
175 /* Create the key for the TSD (thread specific data). */
176 pthread_mutex_lock( &key_lock );
177
178 if (thread_key == -1)
179 pthread_key_create( &thread_key, NULL );
180
181 pthread_mutex_unlock( &key_lock );
182
183 /* Allocate thread structure. */
184 thread = D_CALLOC( 1, sizeof(DirectThread) );
185 if (!thread) {
186 D_OOM();
187 return NULL;
188 }
189
190 /* Write thread information to structure. */
191 thread->name = D_STRDUP( name );
192 thread->type = thread_type;
193 thread->main = thread_main;
194 thread->arg = arg;
195
196 /* Initialize to -1 for synchronization. */
197 thread->thread = (pthread_t) -1;
198 thread->tid = (pid_t) -1;
199
200 /* Initialize mutex and condition. */
201 direct_util_recursive_pthread_mutex_init( &thread->lock );
202 pthread_cond_init( &thread->cond, NULL );
203
204 D_MAGIC_SET( thread, DirectThread );
205
206 /* Initialize scheduling and other parameters. */
207 pthread_attr_init( &attr );
208
209 #ifdef PTHREAD_EXPLICIT_SCHED
210 pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
211 #endif
212
213 /* Select scheduler. */
214 switch (direct_config->thread_scheduler) {
215 case DCTS_FIFO:
216 policy = SCHED_FIFO;
217 break;
218
219 case DCTS_RR:
220 policy = SCHED_RR;
221 break;
222
223 default:
224 policy = SCHED_OTHER;
225 break;
226 }
227
228 if (pthread_attr_setschedpolicy( &attr, policy ))
229 D_PERROR( "Direct/Thread: Could not set scheduling policy to %s!\n", direct_thread_policy_name(policy) );
230
231 /* Read (back) value. */
232 pthread_attr_getschedpolicy( &attr, &policy );
233
234 /* Select priority. */
235 switch (thread->type) {
236 case DTT_CLEANUP:
237 case DTT_INPUT:
238 case DTT_OUTPUT:
239 case DTT_MESSAGING:
240 case DTT_CRITICAL:
241 priority = thread->type * direct_config->thread_priority_scale / 100;
242 break;
243
244 default:
245 priority = direct_config->thread_priority;
246 break;
247 }
248
249 D_DEBUG_AT( Direct_ThreadInit, " -> %s (%d) [%d;%d]\n", direct_thread_policy_name(policy), priority,
250 sched_get_priority_min( policy ), sched_get_priority_max( policy ) );
251
252 if (priority < sched_get_priority_min( policy ))
253 priority = sched_get_priority_min( policy );
254
255 if (priority > sched_get_priority_max( policy ))
256 priority = sched_get_priority_max( policy );
257
258 param.sched_priority = priority;
259
260 if (pthread_attr_setschedparam( &attr, ¶m ))
261 D_PERROR( "Direct/Thread: Could not set scheduling priority to %d!\n", priority );
262
263 /* Select stack size? */
264 if (direct_config->thread_stack_size > 0) {
265 if (pthread_attr_setstacksize( &attr, direct_config->thread_stack_size ))
266 D_PERROR( "Direct/Thread: Could not set stack size to %d!\n", direct_config->thread_stack_size );
267 }
268
269 /* Read (back) value. */
270 pthread_attr_getstacksize( &attr, &stack_size );
271
272 /* Lock the thread mutex. */
273 D_DEBUG_AT( Direct_ThreadInit, " -> locking...\n" );
274 pthread_mutex_lock( &thread->lock );
275
276 /* Create and run the thread. */
277 D_DEBUG_AT( Direct_ThreadInit, " -> creating...\n" );
278 pthread_create( &thread->thread, &attr, direct_thread_main, thread );
279
280 pthread_attr_destroy( &attr );
281
282 pthread_getschedparam( thread->thread, &policy, ¶m );
283
284 D_INFO( "Direct/Thread: Started '%s' (%d) [%s %s/%s %d/%d] <%zu>...\n",
285 name, thread->tid, direct_thread_type_name(thread_type),
286 direct_thread_policy_name(policy), direct_thread_scheduler_name(direct_config->thread_scheduler),
287 param.sched_priority, priority, stack_size );
288
289 #ifdef DIRECT_THREAD_WAIT_INIT
290 /* Wait for completion of the thread's initialization. */
291 while (!thread->init) {
292 D_DEBUG_AT( Direct_ThreadInit, " -> waiting...\n" );
293 pthread_cond_wait( &thread->cond, &thread->lock );
294 }
295
296 D_DEBUG_AT( Direct_ThreadInit, " -> ...thread is running.\n" );
297 #endif
298
299 /* Unlock the thread mutex. */
300 D_DEBUG_AT( Direct_ThreadInit, " -> unlocking...\n" );
301 pthread_mutex_unlock( &thread->lock );
302
303 D_DEBUG_AT( Direct_ThreadInit, " -> returning %p\n", thread );
304
305 return thread;
306 }
307
308 DirectThread *
direct_thread_self(void)309 direct_thread_self( void )
310 {
311 DirectThread *thread = pthread_getspecific( thread_key );
312
313 if (thread)
314 D_MAGIC_ASSERT( thread, DirectThread );
315
316 return thread;
317 }
318
319 const char *
direct_thread_get_name(DirectThread * thread)320 direct_thread_get_name( DirectThread *thread )
321 {
322 D_MAGIC_ASSERT( thread, DirectThread );
323 D_ASSERT( thread->name != NULL );
324
325 return thread->name;
326 }
327
328 pid_t
direct_thread_get_tid(DirectThread * thread)329 direct_thread_get_tid( DirectThread *thread )
330 {
331 D_MAGIC_ASSERT( thread, DirectThread );
332
333 return thread->tid;
334 }
335
336 __attribute__((no_instrument_function))
337 const char *
direct_thread_self_name(void)338 direct_thread_self_name( void )
339 {
340 DirectThread *thread = pthread_getspecific( thread_key );
341
342 /*
343 * This function is called by debugging functions, e.g. debug messages, assertions etc.
344 * Therefore no assertions are made here, because they would loop forever if they fail.
345 */
346
347 return thread ? thread->name : NULL;
348 }
349
350 void
direct_thread_set_name(const char * name)351 direct_thread_set_name( const char *name )
352 {
353 char *copy;
354 DirectThread *thread = pthread_getspecific( thread_key );
355
356 D_DEBUG_AT( Direct_Thread, "%s( '%s' )\n", __FUNCTION__, name );
357
358 /* Support this function for non-direct threads. */
359 if (!thread) {
360 D_DEBUG_AT( Direct_Thread, " -> attaching unknown thread %d\n", direct_gettid() );
361
362 /* Create the key for the TSD (thread specific data). */
363 pthread_mutex_lock( &key_lock );
364
365 if (thread_key == -1)
366 pthread_key_create( &thread_key, NULL );
367
368 pthread_mutex_unlock( &key_lock );
369
370
371 thread = D_CALLOC( 1, sizeof(DirectThread) );
372 if (!thread) {
373 D_OOM();
374 return;
375 }
376
377 thread->thread = pthread_self();
378 thread->tid = direct_gettid();
379
380 D_MAGIC_SET( thread, DirectThread );
381
382 pthread_setspecific( thread_key, thread );
383 }
384 else
385 D_DEBUG_AT( Direct_Thread, " -> was '%s' (%d)\n", thread->name, direct_gettid() );
386
387 /* Duplicate string. */
388 copy = D_STRDUP( name );
389 if (!copy) {
390 D_OOM();
391 return;
392 }
393
394 /* Free old string. */
395 if (thread->name)
396 D_FREE( thread->name );
397
398 /* Keep the copy. */
399 thread->name = copy;
400 }
401
402 DirectResult
direct_thread_wait(DirectThread * thread,int timeout_ms)403 direct_thread_wait( DirectThread *thread, int timeout_ms )
404 {
405 unsigned int old_counter = thread->counter;
406
407 D_MAGIC_ASSERT( thread, DirectThread );
408 D_ASSERT( thread->thread != -1 );
409
410 D_ASSUME( !thread->canceled );
411
412 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d, %dms )\n", __FUNCTION__,
413 thread->main, thread->name, thread->tid, timeout_ms );
414
415 while (old_counter == thread->counter && !thread->terminated)
416 pthread_cond_wait( &thread->cond, &thread->lock );
417
418 if (thread->terminated)
419 return DR_DEAD;
420
421 return DR_OK;
422 }
423
424 void
direct_thread_notify(DirectThread * thread)425 direct_thread_notify( DirectThread *thread )
426 {
427 D_MAGIC_ASSERT( thread, DirectThread );
428 D_ASSERT( thread->thread != -1 );
429
430 D_ASSUME( !thread->canceled );
431
432 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
433
434 pthread_mutex_lock( &thread->lock );
435
436 thread->counter++;
437
438 pthread_mutex_unlock( &thread->lock );
439
440 pthread_cond_broadcast( &thread->cond );
441 }
442
443 void
direct_thread_lock(DirectThread * thread)444 direct_thread_lock( DirectThread *thread )
445 {
446 D_MAGIC_ASSERT( thread, DirectThread );
447 D_ASSERT( thread->thread != -1 );
448
449 D_ASSUME( !thread->canceled );
450
451 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
452
453 pthread_mutex_lock( &thread->lock );
454 }
455
456 void
direct_thread_unlock(DirectThread * thread)457 direct_thread_unlock( DirectThread *thread )
458 {
459 D_MAGIC_ASSERT( thread, DirectThread );
460 D_ASSERT( thread->thread != -1 );
461
462 D_ASSUME( !thread->canceled );
463
464 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
465
466 pthread_mutex_unlock( &thread->lock );
467 }
468
469 void
direct_thread_terminate(DirectThread * thread)470 direct_thread_terminate( DirectThread *thread )
471 {
472 D_MAGIC_ASSERT( thread, DirectThread );
473 D_ASSERT( thread->thread != -1 );
474 D_ASSUME( !pthread_equal( thread->thread, pthread_self() ) );
475
476 D_ASSUME( !thread->canceled );
477
478 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
479
480 thread->terminated = true;
481
482 direct_thread_notify( thread );
483 }
484
485 void
direct_thread_cancel(DirectThread * thread)486 direct_thread_cancel( DirectThread *thread )
487 {
488 D_MAGIC_ASSERT( thread, DirectThread );
489 D_ASSERT( thread->thread != -1 );
490 D_ASSERT( !pthread_equal( thread->thread, pthread_self() ) );
491
492 D_ASSUME( !thread->canceled );
493
494 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
495
496 thread->canceled = true;
497
498 #if DIRECT_BUILD_NO_PTHREAD_CANCEL
499 D_UNIMPLEMENTED();
500 #else
501 pthread_cancel( thread->thread );
502 #endif
503 }
504
505 bool
direct_thread_is_canceled(DirectThread * thread)506 direct_thread_is_canceled( DirectThread *thread )
507 {
508 D_MAGIC_ASSERT( thread, DirectThread );
509
510 return thread->canceled;
511 }
512
513 void
direct_thread_detach(DirectThread * thread)514 direct_thread_detach( DirectThread *thread )
515 {
516 D_MAGIC_ASSERT( thread, DirectThread );
517 D_ASSERT( thread->thread != -1 );
518 D_ASSERT( !pthread_equal( thread->thread, pthread_self() ) );
519
520 D_ASSUME( !thread->canceled );
521
522 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
523
524 thread->detached = true;
525
526 pthread_detach( thread->thread );
527 }
528
529 bool
direct_thread_is_detached(DirectThread * thread)530 direct_thread_is_detached( DirectThread *thread )
531 {
532 D_MAGIC_ASSERT( thread, DirectThread );
533
534 return thread->detached;
535 }
536
537 void
direct_thread_testcancel(DirectThread * thread)538 direct_thread_testcancel( DirectThread *thread )
539 {
540 D_MAGIC_ASSERT( thread, DirectThread );
541 D_ASSERT( thread->thread != -1 );
542 D_ASSERT( pthread_equal( thread->thread, pthread_self() ) );
543
544 #if DIRECT_BUILD_NO_PTHREAD_CANCEL
545 D_UNIMPLEMENTED();
546 #else
547 /* Quick check before calling the pthread function. */
548 if (thread->canceled)
549 pthread_testcancel();
550 #endif
551 }
552
553 void
direct_thread_join(DirectThread * thread)554 direct_thread_join( DirectThread *thread )
555 {
556 D_MAGIC_ASSERT( thread, DirectThread );
557 D_ASSERT( thread->thread != -1 );
558
559 D_ASSUME( !pthread_equal( thread->thread, pthread_self() ) );
560 D_ASSUME( !thread->joining );
561 D_ASSUME( !thread->joined );
562 D_ASSUME( !thread->detached );
563
564 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
565
566 if (thread->detached) {
567 D_DEBUG_AT( Direct_Thread, " -> DETACHED!\n" );
568 return;
569 }
570
571 if (!thread->joining && !pthread_equal( thread->thread, pthread_self() )) {
572 thread->joining = true;
573
574 D_DEBUG_AT( Direct_Thread, " -> joining...\n" );
575
576 pthread_join( thread->thread, NULL );
577
578 thread->joined = true;
579
580 D_DEBUG_AT( Direct_Thread, " -> joined.\n" );
581 }
582 }
583
584 bool
direct_thread_is_joined(DirectThread * thread)585 direct_thread_is_joined( DirectThread *thread )
586 {
587 D_MAGIC_ASSERT( thread, DirectThread );
588
589 return thread->joined;
590 }
591
592 void
direct_thread_destroy(DirectThread * thread)593 direct_thread_destroy( DirectThread *thread )
594 {
595 D_MAGIC_ASSERT( thread, DirectThread );
596 D_ASSUME( !pthread_equal( thread->thread, pthread_self() ) );
597 D_ASSUME( !thread->detached );
598
599 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
600
601 if (thread->detached) {
602 D_DEBUG_AT( Direct_Thread, " -> DETACHED!\n" );
603 return;
604 }
605
606 if (!thread->joined && !pthread_equal( thread->thread, pthread_self() )) {
607 if (thread->canceled)
608 D_DEBUG_AT( Direct_Thread, " -> cancled but not joined!\n" );
609 else {
610 D_DEBUG_AT( Direct_Thread, " -> still running!\n" );
611
612 if (thread->name)
613 D_ERROR( "Direct/Thread: Canceling '%s' (%d)!\n", thread->name, thread->tid );
614 else
615 D_ERROR( "Direct/Thread: Canceling %d!\n", thread->tid );
616
617 thread->detached = true;
618
619 pthread_detach( thread->thread );
620
621 direct_thread_cancel( thread );
622
623 return;
624 }
625 }
626
627 D_MAGIC_CLEAR( thread );
628
629 D_FREE( thread->name );
630 D_FREE( thread );
631 }
632
633 /******************************************************************************/
634
635 #if DIRECT_BUILD_TEXT
636 const char *
direct_thread_type_name(DirectThreadType type)637 direct_thread_type_name( DirectThreadType type )
638 {
639 switch (type) {
640 case DTT_DEFAULT:
641 return "DEFAULT";
642
643 case DTT_CLEANUP:
644 return "CLEANUP";
645
646 case DTT_INPUT:
647 return "INPUT";
648
649 case DTT_OUTPUT:
650 return "OUTPUT";
651
652 case DTT_MESSAGING:
653 return "MESSAGING";
654
655 case DTT_CRITICAL:
656 return "CRITICAL";
657 }
658
659 return "<unknown>";
660 }
661
662 const char *
direct_thread_scheduler_name(DirectConfigThreadScheduler scheduler)663 direct_thread_scheduler_name( DirectConfigThreadScheduler scheduler )
664 {
665 switch (scheduler) {
666 case DCTS_OTHER:
667 return "OTHER";
668
669 case DCTS_FIFO:
670 return "FIFO";
671
672 case DCTS_RR:
673 return "RR";
674 }
675
676 return "<unknown>";
677 }
678
679 const char *
direct_thread_policy_name(int policy)680 direct_thread_policy_name( int policy )
681 {
682 switch (policy) {
683 case SCHED_OTHER:
684 return "OTHER";
685
686 case SCHED_FIFO:
687 return "FIFO";
688
689 case SCHED_RR:
690 return "RR";
691 }
692
693 return "<unknown>";
694 }
695 #endif
696
697 /******************************************************************************/
698
699 static void
direct_thread_cleanup(void * arg)700 direct_thread_cleanup( void *arg )
701 {
702 DirectThread *thread = arg;
703
704 D_MAGIC_ASSERT( thread, DirectThread );
705
706 D_DEBUG_AT( Direct_Thread, "%s( %p, '%s' %d )\n", __FUNCTION__, thread->main, thread->name, thread->tid );
707
708 if (thread->detached) {
709 D_MAGIC_CLEAR( thread );
710
711 D_FREE( thread->name );
712 D_FREE( thread );
713 }
714 }
715
716 /******************************************************************************/
717
718 static void *
direct_thread_main(void * arg)719 direct_thread_main( void *arg )
720 {
721 void *ret;
722 DirectThread *thread = arg;
723 DirectThreadInitHandler *handler;
724 pid_t tid;
725
726 tid = direct_gettid();
727
728 D_DEBUG_AT( Direct_ThreadInit, "%s( %p ) <- tid %d\n", __FUNCTION__, arg, tid );
729
730 D_DEBUG_AT( Direct_ThreadInit, " -> starting...\n" );
731
732 D_MAGIC_ASSERT( thread, DirectThread );
733
734 pthread_cleanup_push( direct_thread_cleanup, thread );
735
736
737 pthread_setspecific( thread_key, thread );
738
739 thread->tid = tid;
740
741
742 /* Call all init handlers. */
743 pthread_mutex_lock( &handler_lock );
744
745 direct_list_foreach (handler, handlers)
746 handler->func( thread, handler->arg );
747
748 pthread_mutex_unlock( &handler_lock );
749
750
751 /* Have all signals handled by the main thread. */
752 if (direct_config->thread_block_signals)
753 direct_signals_block_all();
754
755 /* Lock the thread mutex. */
756 D_DEBUG_AT( Direct_ThreadInit, " -> locking...\n" );
757 pthread_mutex_lock( &thread->lock );
758
759 /* Indicate that our initialization has completed. */
760 thread->init = true;
761
762 #ifdef DIRECT_THREAD_WAIT_INIT
763 D_DEBUG_AT( Direct_ThreadInit, " -> signalling...\n" );
764 pthread_cond_signal( &thread->cond );
765 #endif
766
767 /* Unlock the thread mutex. */
768 D_DEBUG_AT( Direct_ThreadInit, " -> unlocking...\n" );
769 pthread_mutex_unlock( &thread->lock );
770
771 if (thread->joining) {
772 D_DEBUG_AT( Direct_Thread, " -> Being joined before entering main routine!\n" );
773 return NULL;
774 }
775
776 D_MAGIC_ASSERT( thread, DirectThread );
777
778 /* Call main routine. */
779 D_DEBUG_AT( Direct_ThreadInit, " -> running...\n" );
780 ret = thread->main( thread, thread->arg );
781
782 D_DEBUG_AT( Direct_Thread, " -> Returning %p from '%s' (%s, %d)...\n",
783 ret, thread->name, direct_thread_type_name(thread->type), thread->tid );
784
785 D_MAGIC_ASSERT( thread, DirectThread );
786
787 pthread_cleanup_pop( 1 );
788
789 return ret;
790 }
791
792