1 | /*
|
---|
2 | * $Id: thread-st.h$
|
---|
3 | * pthread version
|
---|
4 | * by Wolfram Gloger 2004
|
---|
5 | */
|
---|
6 |
|
---|
7 | #include <pthread.h>
|
---|
8 | #include <stdio.h>
|
---|
9 |
|
---|
10 | pthread_cond_t finish_cond = PTHREAD_COND_INITIALIZER;
|
---|
11 | pthread_mutex_t finish_mutex = PTHREAD_MUTEX_INITIALIZER;
|
---|
12 |
|
---|
13 | #ifndef USE_PTHREADS_STACKS
|
---|
14 | #define USE_PTHREADS_STACKS 0
|
---|
15 | #endif
|
---|
16 |
|
---|
17 | #ifndef STACKSIZE
|
---|
18 | #define STACKSIZE 32768
|
---|
19 | #endif
|
---|
20 |
|
---|
21 | struct thread_st {
|
---|
22 | char *sp; /* stack pointer, can be 0 */
|
---|
23 | void (*func)(struct thread_st* st); /* must be set by user */
|
---|
24 | pthread_t id;
|
---|
25 | int flags;
|
---|
26 | struct user_data u;
|
---|
27 | };
|
---|
28 |
|
---|
29 | static void
|
---|
30 | thread_init(void)
|
---|
31 | {
|
---|
32 | printf("Using posix threads.\n");
|
---|
33 | pthread_cond_init(&finish_cond, NULL);
|
---|
34 | pthread_mutex_init(&finish_mutex, NULL);
|
---|
35 | }
|
---|
36 |
|
---|
37 | static void *
|
---|
38 | thread_wrapper(void *ptr)
|
---|
39 | {
|
---|
40 | struct thread_st *st = (struct thread_st*)ptr;
|
---|
41 |
|
---|
42 | /*printf("begin %p\n", st->sp);*/
|
---|
43 | st->func(st);
|
---|
44 | pthread_mutex_lock(&finish_mutex);
|
---|
45 | st->flags = 1;
|
---|
46 | pthread_mutex_unlock(&finish_mutex);
|
---|
47 | pthread_cond_signal(&finish_cond);
|
---|
48 | /*printf("end %p\n", st->sp);*/
|
---|
49 | return NULL;
|
---|
50 | }
|
---|
51 |
|
---|
52 | /* Create a thread. */
|
---|
53 | static int
|
---|
54 | thread_create(struct thread_st *st)
|
---|
55 | {
|
---|
56 | st->flags = 0;
|
---|
57 | {
|
---|
58 | pthread_attr_t* attr_p = 0;
|
---|
59 | #if USE_PTHREADS_STACKS
|
---|
60 | pthread_attr_t attr;
|
---|
61 |
|
---|
62 | pthread_attr_init (&attr);
|
---|
63 | if(!st->sp)
|
---|
64 | st->sp = malloc(STACKSIZE+16);
|
---|
65 | if(!st->sp)
|
---|
66 | return -1;
|
---|
67 | if(pthread_attr_setstacksize(&attr, STACKSIZE))
|
---|
68 | fprintf(stderr, "error setting stacksize");
|
---|
69 | else
|
---|
70 | pthread_attr_setstackaddr(&attr, st->sp + STACKSIZE);
|
---|
71 | /*printf("create %p\n", st->sp);*/
|
---|
72 | attr_p = &attr;
|
---|
73 | #endif
|
---|
74 | return pthread_create(&st->id, attr_p, thread_wrapper, st);
|
---|
75 | }
|
---|
76 | return 0;
|
---|
77 | }
|
---|
78 |
|
---|
79 | /* Wait for one of several subthreads to finish. */
|
---|
80 | static void
|
---|
81 | wait_for_thread(struct thread_st st[], int n_thr,
|
---|
82 | int (*end_thr)(struct thread_st*))
|
---|
83 | {
|
---|
84 | int i;
|
---|
85 |
|
---|
86 | pthread_mutex_lock(&finish_mutex);
|
---|
87 | for(;;) {
|
---|
88 | int term = 0;
|
---|
89 | for(i=0; i<n_thr; i++)
|
---|
90 | if(st[i].flags) {
|
---|
91 | /*printf("joining %p\n", st[i].sp);*/
|
---|
92 | if(pthread_join(st[i].id, NULL) == 0) {
|
---|
93 | st[i].flags = 0;
|
---|
94 | if(end_thr)
|
---|
95 | end_thr(&st[i]);
|
---|
96 | } else
|
---|
97 | fprintf(stderr, "can't join\n");
|
---|
98 | ++term;
|
---|
99 | }
|
---|
100 | if(term > 0)
|
---|
101 | break;
|
---|
102 | pthread_cond_wait(&finish_cond, &finish_mutex);
|
---|
103 | }
|
---|
104 | pthread_mutex_unlock(&finish_mutex);
|
---|
105 | }
|
---|
106 |
|
---|
107 | /*
|
---|
108 | * Local variables:
|
---|
109 | * tab-width: 4
|
---|
110 | * End:
|
---|
111 | */
|
---|