1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 * Copyright (c) 2008 Likewise Software, Inc. All rights reserved.
4 *
5 * @APPLE_LICENSE_HEADER_START@
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 the
15 *     documentation and/or other materials provided with the distribution.
16 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
17 *     contributors may be used to endorse or promote products derived from
18 *     this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Portions of this software have been released under the following terms:
32 *
33 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
34 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
35 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
36 *
37 * To anyone who acknowledges that this file is provided "AS IS"
38 * without any express or implied warranty:
39 * permission to use, copy, modify, and distribute this file for any
40 * purpose is hereby granted without fee, provided that the above
41 * copyright notices and this notice appears in all source code copies,
42 * and that none of the names of Open Software Foundation, Inc., Hewlett-
43 * Packard Company or Digital Equipment Corporation be used
44 * in advertising or publicity pertaining to distribution of the software
45 * without specific, written prior permission.  Neither Open Software
46 * Foundation, Inc., Hewlett-Packard Company nor Digital
47 * Equipment Corporation makes any representations about the suitability
48 * of this software for any purpose.
49 *
50 * Copyright (c) 2007, Novell, Inc. All rights reserved.
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 *
55 * 1.  Redistributions of source code must retain the above copyright
56 *     notice, this list of conditions and the following disclaimer.
57 * 2.  Redistributions in binary form must reproduce the above copyright
58 *     notice, this list of conditions and the following disclaimer in the
59 *     documentation and/or other materials provided with the distribution.
60 * 3.  Neither the name of Novell Inc. nor the names of its contributors
61 *     may be used to endorse or promote products derived from this
62 *     this software without specific prior written permission.
63 *
64 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
65 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
66 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
67 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
68 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
69 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
70 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
71 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
72 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
73 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
74 *
75 * @APPLE_LICENSE_HEADER_END@
76 */
77
78#include <config.h>
79#include <errno.h>
80
81#include "dcethread-private.h"
82#include "dcethread-util.h"
83#include "dcethread-debug.h"
84
85#ifdef API
86
87int
88dcethread_interrupt(dcethread* thread)
89{
90    dcethread__lock(thread);
91    dcethread__interrupt(thread);
92    dcethread__unlock(thread);
93
94    return dcethread__set_errno(0);
95}
96
97int
98dcethread_interrupt_throw(dcethread* thread)
99{
100    DCETHREAD_WRAP_THROW(dcethread_interrupt(thread));
101}
102
103#endif /* API */
104
105#ifdef TEST
106
107#include "dcethread-test.h"
108
109static void*
110basic_thread(void* data)
111{
112    volatile int interrupt_caught = 0;
113
114    DCETHREAD_TRY
115    {
116	MU_ASSERT(!interrupt_caught);
117	while (1)
118	{
119	    dcethread_checkinterrupt();
120	    dcethread_yield();
121	}
122    }
123    DCETHREAD_CATCH(dcethread_interrupt_e)
124    {
125	MU_ASSERT(!interrupt_caught);
126	interrupt_caught = 1;
127    }
128    DCETHREAD_ENDTRY;
129
130    MU_ASSERT(interrupt_caught);
131
132    return NULL;
133}
134
135MU_TEST(dcethread_interrupt, basic)
136{
137    dcethread* thread;
138
139    MU_TRY_DCETHREAD( dcethread_create(&thread, NULL, basic_thread, NULL) );
140    MU_TRY_DCETHREAD( dcethread_interrupt(thread) );
141    MU_TRY_DCETHREAD( dcethread_join(thread, NULL) );
142}
143
144MU_TEST(dcethread_interrupt, self)
145{
146    volatile int interrupt_caught = 0;
147
148    DCETHREAD_TRY
149    {
150        MU_ASSERT(!interrupt_caught);
151        dcethread_interrupt(dcethread_self());
152        dcethread_checkinterrupt();
153    }
154    DCETHREAD_CATCH(dcethread_interrupt_e)
155    {
156        MU_ASSERT(!interrupt_caught);
157        interrupt_caught = 1;
158    }
159    DCETHREAD_ENDTRY;
160
161    MU_ASSERT(interrupt_caught);
162}
163
164MU_TEST(dcethread_interrupt, disable)
165{
166    DCETHREAD_TRY
167    {
168        dcethread_enableinterrupt(0);
169        dcethread_interrupt(dcethread_self());
170        dcethread_checkinterrupt();
171    }
172    DCETHREAD_CATCH(dcethread_interrupt_e)
173    {
174        MU_ASSERT_NOT_REACHED();
175    }
176    DCETHREAD_ENDTRY;
177}
178
179MU_TEST(dcethread_interrupt, disable_enable)
180{
181    volatile int interrupt_caught = 0;
182
183    DCETHREAD_TRY
184    {
185        dcethread_enableinterrupt(0);
186        dcethread_interrupt(dcethread_self());
187        dcethread_enableinterrupt(1);
188        dcethread_checkinterrupt();
189    }
190    DCETHREAD_CATCH(dcethread_interrupt_e)
191    {
192        MU_ASSERT(!interrupt_caught);
193        interrupt_caught = 1;
194    }
195    DCETHREAD_ENDTRY;
196
197    MU_ASSERT(interrupt_caught);
198}
199
200static dcethread_mutex bug_6386_mutex = DCETHREAD_MUTEX_INITIALIZER;
201
202static void*
203bug_6386_thread(void* data)
204{
205    MU_TRY_DCETHREAD(dcethread_mutex_lock(&bug_6386_mutex));
206    MU_TRY_DCETHREAD(dcethread_mutex_unlock(&bug_6386_mutex));
207
208    return data;
209}
210
211/* Test for regression of bug 6386, which causes
212   deadlock when a thread interrupted during a
213   dcethread_mutex_lock of a mutex held by
214   the interrupting thread */
215MU_TEST(dcethread_interrupt, bug_6386)
216{
217    dcethread* thread = NULL;
218
219    MU_TRY_DCETHREAD(dcethread_mutex_lock(&bug_6386_mutex));
220    MU_TRY_DCETHREAD(dcethread_create(&thread, NULL, bug_6386_thread, NULL));
221    MU_TRY_DCETHREAD(dcethread_interrupt(thread));
222    MU_TRY_DCETHREAD(dcethread_mutex_unlock(&bug_6386_mutex));
223    MU_TRY_DCETHREAD(dcethread_join(thread, NULL));
224}
225
226#endif /* TEST */
227