GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/thread/rthread.c Lines: 0 36 0.0 %
Date: 2017-11-13 Branches: 0 16 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: rthread.c,v 1.6 2017/11/04 22:53:57 jca Exp $ */
2
/*
3
 * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
4
 * All Rights Reserved.
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
/*
19
 * The infrastructure of rthreads
20
 */
21
22
#include <pthread.h>
23
#include <stdlib.h>
24
#include <tib.h>
25
#include <unistd.h>
26
27
#include "rthread.h"
28
29
#define RTHREAD_ENV_DEBUG	"RTHREAD_DEBUG"
30
31
int _rthread_debug_level;
32
33
static int _threads_inited;
34
35
struct pthread _initial_thread = {
36
	.flags_lock = _SPINLOCK_UNLOCKED,
37
	.name = "Original thread",
38
};
39
40
/*
41
 * internal support functions
42
 */
43
void
44
_spinlock(volatile _atomic_lock_t *lock)
45
{
46
	while (_atomic_lock(lock))
47
		sched_yield();
48
}
49
DEF_STRONG(_spinlock);
50
51
int
52
_spinlocktry(volatile _atomic_lock_t *lock)
53
{
54
	return 0 == _atomic_lock(lock);
55
}
56
57
void
58
_spinunlock(volatile _atomic_lock_t *lock)
59
{
60
	*lock = _ATOMIC_LOCK_UNLOCKED;
61
}
62
DEF_STRONG(_spinunlock);
63
64
static void
65
_rthread_init(void)
66
{
67
	pthread_t thread = &_initial_thread;
68
	struct tib *tib;
69
70
	if (_threads_inited)
71
		return;
72
73
	tib = TIB_GET();
74
	tib->tib_thread = thread;
75
	thread->tib = tib;
76
77
	thread->donesem.lock = _SPINLOCK_UNLOCKED;
78
	tib->tib_thread_flags = TIB_THREAD_INITIAL_STACK;
79
80
	/*
81
	 * Set the debug level from an environment string.
82
	 * Bogus values are silently ignored.
83
	 */
84
	if (! issetugid()) {
85
		char *envp = getenv(RTHREAD_ENV_DEBUG);
86
87
		if (envp != NULL) {
88
			char *rem;
89
90
			_rthread_debug_level = (int) strtol(envp, &rem, 0);
91
			if (*rem != '\0' || _rthread_debug_level < 0)
92
				_rthread_debug_level = 0;
93
		}
94
	}
95
96
	_threads_inited = 1;
97
}
98
99
/*
100
 * real pthread functions
101
 */
102
pthread_t
103
pthread_self(void)
104
{
105
	if (__predict_false(!_threads_inited))
106
		_rthread_init();
107
108
	return TIB_GET()->tib_thread;
109
}
110
DEF_STRONG(pthread_self);
111
112
void
113
pthread_exit(void *retval)
114
{
115
	struct rthread_cleanup_fn *clfn;
116
	struct tib *tib;
117
	pthread_t thread = pthread_self();
118
119
	tib = thread->tib;
120
121
	if (tib->tib_cantcancel & CANCEL_DYING) {
122
		/*
123
		 * Called pthread_exit() from destructor or cancelation
124
		 * handler: blow up.  XXX write something to stderr?
125
		 */
126
		abort();
127
		//_exit(42);
128
	}
129
130
	tib->tib_cantcancel |= CANCEL_DYING;
131
132
	thread->retval = retval;
133
134
	for (clfn = thread->cleanup_fns; clfn; ) {
135
		struct rthread_cleanup_fn *oclfn = clfn;
136
		clfn = clfn->next;
137
		oclfn->fn(oclfn->arg);
138
		free(oclfn);
139
	}
140
	_rthread_tls_destructors(thread);
141
142
	if (_thread_cb.tc_thread_release != NULL)
143
		_thread_cb.tc_thread_release(thread);
144
145
	__threxit(&tib->tib_tid);
146
	for(;;);
147
}
148
DEF_STRONG(pthread_exit);
149
150
int
151
pthread_equal(pthread_t t1, pthread_t t2)
152
{
153
	return (t1 == t2);
154
}
155