vkernel - more crit section work to avoid pthread reentrancy.
[dragonfly.git] / sys / platform / vkernel / platform / cothread.c
CommitLineData
9c2ed617
MD
1/*
2 * Copyright (c) 2008 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
27c3aec1 34 * $DragonFly: src/sys/platform/vkernel/platform/cothread.c,v 1.3 2008/05/07 17:19:47 dillon Exp $
9c2ed617
MD
35 */
36/*
37 * Provides the vkernel with an asynchronous I/O mechanism using pthreads
38 * which operates outside the cpu abstraction. Cothreads are intended to
39 * operate like DMA engines and may ONLY make libc and cothread_*() calls.
40 * The cothread may NOT call into the vkernel since abstractions like
41 * 'mycpu' do not exist for it.
42 */
43
44#include <sys/interrupt.h>
45#include <sys/kernel.h>
46#include <sys/memrange.h>
47#include <sys/tls.h>
48#include <sys/types.h>
49
50#include <vm/vm_extern.h>
51#include <vm/vm_kern.h>
52#include <vm/vm_object.h>
53#include <vm/vm_page.h>
54
55#include <machine/cpu.h>
56#include <machine/cpufunc.h>
57#include <machine/globaldata.h>
58#include <machine/md_var.h>
59#include <machine/pmap.h>
60#include <machine/smp.h>
61#include <machine/tls.h>
62#include <machine/cothread.h>
63
64#include <unistd.h>
65#include <pthread.h>
66#include <signal.h>
67#include <stdio.h>
68
d19705b2
MD
69static void cothread_thread(void *arg);
70
9c2ed617
MD
71/*
72 * Create a co-processor thread for a virtual kernel. This thread operates
73 * outside of the virtual kernel cpu abstraction and may only make direct
74 * cothread and libc calls.
75 */
76cothread_t
77cothread_create(void (*thr_func)(cothread_t cotd),
78 void (*thr_intr)(cothread_t cotd),
79 void *arg, const char *name)
80{
81 cothread_t cotd;
82
83 cotd = kmalloc(sizeof(*cotd), M_DEVBUF, M_WAITOK|M_ZERO);
d19705b2
MD
84 cotd->thr_intr = thr_intr;
85 cotd->thr_func = thr_func;
9c2ed617 86 cotd->arg = arg;
03bcb4ab 87 crit_enter();
9c2ed617
MD
88 pthread_mutex_init(&cotd->mutex, NULL);
89 pthread_cond_init(&cotd->cond, NULL);
03bcb4ab 90 crit_exit();
9c2ed617
MD
91
92 cotd->pintr = pthread_self();
93
d19265de 94 cotd->intr_id = register_int(1, (void *)thr_intr, cotd, name, NULL, 0);
9c2ed617
MD
95
96 /*
97 * The vkernel's cpu_disable_intr() masks signals. We don't want
98 * our coprocessor thread taking any unix signals :-)
99 */
03bcb4ab 100 crit_enter();
65905e94 101 cpu_mask_all_signals();
d19705b2 102 pthread_create(&cotd->pthr, NULL, (void *)cothread_thread, cotd);
65905e94 103 cpu_unmask_all_signals();
03bcb4ab 104 crit_exit();
9c2ed617
MD
105 return(cotd);
106}
107
d19265de
MD
108/*
109 * Wait for the target thread to terminate and then destroy the cothread
110 * structure.
111 */
112void
113cothread_delete(cothread_t *cotdp)
114{
115 cothread_t cotd;
116
117 if ((cotd = *cotdp) != NULL) {
118 unregister_int(cotd->intr_id);
03bcb4ab 119 crit_enter();
d19265de 120 pthread_join(cotd->pthr, NULL);
03bcb4ab 121 crit_exit();
d19265de
MD
122 kfree(cotd, M_DEVBUF);
123 *cotdp = NULL;
124 }
125}
126
d19705b2
MD
127static void
128cothread_thread(void *arg)
129{
130 cothread_t cotd = arg;
131 int dummy = 0;
132
65905e94 133 cpu_mask_all_signals(); /* XXX remove me? should already be masked */
27c3aec1
MD
134 /*
135 * %fs (aka mycpu) is illegal in cothreads. Note that %fs is used
136 * by pthreads.
137 */
d19705b2
MD
138 tls_set_fs(&dummy, sizeof(dummy));
139 cotd->thr_func(cotd);
140}
141
9c2ed617
MD
142/*
143 * Called by the cothread to generate an interrupt back to the vkernel.
144 */
145void
146cothread_intr(cothread_t cotd)
147{
148 pthread_kill(cotd->pintr, SIGIO);
149}
150
151/*
152 * Called by the vkernel to wakeup a cothread.
153 */
154void
155cothread_signal(cothread_t cotd)
156{
03bcb4ab 157 crit_enter();
9c2ed617 158 pthread_cond_signal(&cotd->cond);
03bcb4ab 159 crit_exit();
9c2ed617
MD
160}
161
162/*
163 * Called by the cothread to wait for the vkernel to call cothread_signal().
164 */
165void
166cothread_wait(cothread_t cotd)
167{
168 pthread_cond_wait(&cotd->cond, &cotd->mutex);
169}
170
03bcb4ab
MD
171/*
172 * Typically called by kernel thread or cothread
173 */
9c2ed617 174void
94131955 175cothread_lock(cothread_t cotd, int is_cotd)
9c2ed617 176{
94131955
MD
177 if (is_cotd) {
178 pthread_mutex_lock(&cotd->mutex);
179 } else {
180 crit_enter();
181 pthread_mutex_lock(&cotd->mutex);
182 crit_exit();
183 }
9c2ed617
MD
184}
185
186void
94131955 187cothread_unlock(cothread_t cotd, int is_cotd)
9c2ed617 188{
94131955
MD
189 if (is_cotd) {
190 pthread_mutex_unlock(&cotd->mutex);
191 } else {
192 crit_enter();
193 pthread_mutex_unlock(&cotd->mutex);
194 crit_exit();
195 }
9c2ed617
MD
196}
197