2
* ivykis, an event handling library
3
* Copyright (C) 2010 Lennert Buytenhek
4
* Dedicated to Marija Kulikova.
6
* This library is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License version
8
* 2.1 as published by the Free Software Foundation.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU Lesser General Public License version 2.1 for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License version 2.1 along with this library; if not, write to the
17
* Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
18
* Boston, MA 02110-1301, USA.
25
#include <iv_thread.h>
29
/* data structures and global data ******************************************/
31
struct list_head list;
35
void (*start_routine)(void *);
41
struct list_head child_threads;
45
#define child_threads __tls_deref(child_threads)
47
static int iv_thread_debug;
50
/* gettid *******************************************************************/
52
/* Older FreeBSDs (6.1) don't include ucontext.h in thr.h. */
53
#include <sys/ucontext.h>
58
#if defined(linux) && defined(__x86_64__)
59
#define __NR_gettid 186
60
#elif defined(linux) && defined(__i386__)
61
#define __NR_gettid 224
65
static pid_t gettid(void)
71
tid = syscall(__NR_gettid);
72
#elif defined(__FreeBSD__)
82
/* callee thread ************************************************************/
83
static void iv_thread_cleanup_handler(void *_thr)
85
struct iv_thread *thr = _thr;
88
fprintf(stderr, "iv_thread: [%s] was canceled\n", thr->name);
90
iv_event_post(&thr->dead);
93
static void *iv_thread_handler(void *_thr)
95
struct iv_thread *thr = _thr;
99
pthread_cleanup_push(iv_thread_cleanup_handler, thr);
100
thr->start_routine(thr->arg);
101
pthread_cleanup_pop(0);
104
fprintf(stderr, "iv_thread: [%s] terminating normally\n",
107
iv_event_post(&thr->dead);
113
/* calling thread ***********************************************************/
114
static void iv_thread_died(void *_thr)
116
struct iv_thread *thr = _thr;
119
fprintf(stderr, "iv_thread: [%s] joined\n", thr->name);
121
list_del(&thr->list);
122
iv_event_unregister(&thr->dead);
127
int iv_thread_create(char *name, void (*start_routine)(void *), void *arg)
129
struct iv_thread *thr;
134
thr = malloc(sizeof(*thr));
138
IV_EVENT_INIT(&thr->dead);
139
thr->dead.cookie = thr;
140
thr->dead.handler = iv_thread_died;
141
iv_event_register(&thr->dead);
143
thr->name = strdup(name);
145
thr->start_routine = start_routine;
148
ret = pthread_attr_init(&attr);
152
ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
156
ret = pthread_create(&t, &attr, iv_thread_handler, thr);
160
pthread_attr_destroy(&attr);
162
if (child_threads.next == NULL)
163
INIT_LIST_HEAD(&child_threads);
164
list_add_tail(&thr->list, &child_threads);
167
fprintf(stderr, "iv_thread: [%s] started\n", name);
172
pthread_attr_destroy(&attr);
175
iv_event_unregister(&thr->dead);
179
fprintf(stderr, "iv_thread: [%s] failed to start\n", name);
184
void iv_thread_set_debug_state(int state)
186
iv_thread_debug = !!state;
189
void iv_thread_list_children(void)
191
struct list_head *lh;
193
fprintf(stderr, "tid\tname\n");
194
fprintf(stderr, "%d\tself\n", gettid());
196
list_for_each (lh, &child_threads) {
197
struct iv_thread *thr;
199
thr = list_entry(lh, struct iv_thread, list);
200
fprintf(stderr, "%d\t%s\n", thr->tid, thr->name);