xref: /netbsd-src/tests/lib/libobjc/t_threads.m (revision ddd5644b2ef20c4a0611da9cf1ebe3864214940f)
1*ddd5644bSchristos/* $NetBSD: t_threads.m,v 1.2 2013/10/31 21:02:11 christos Exp $ */
2cb5d4b08Sjmmv
3cb5d4b08Sjmmv/*
4cb5d4b08Sjmmv * Copyright (c) 2010 The NetBSD Foundation, Inc.
5cb5d4b08Sjmmv * All rights reserved.
6cb5d4b08Sjmmv *
7cb5d4b08Sjmmv * Redistribution and use in source and binary forms, with or without
8cb5d4b08Sjmmv * modification, are permitted provided that the following conditions
9cb5d4b08Sjmmv * are met:
10cb5d4b08Sjmmv * 1. Redistributions of source code must retain the above copyright
11cb5d4b08Sjmmv *    notice, this list of conditions and the following disclaimer.
12cb5d4b08Sjmmv * 2. Redistributions in binary form must reproduce the above copyright
13cb5d4b08Sjmmv *    notice, this list of conditions and the following disclaimer in the
14cb5d4b08Sjmmv *    documentation and/or other materials provided with the distribution.
15cb5d4b08Sjmmv *
16cb5d4b08Sjmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17cb5d4b08Sjmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18cb5d4b08Sjmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19cb5d4b08Sjmmv * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20cb5d4b08Sjmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21cb5d4b08Sjmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22cb5d4b08Sjmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23cb5d4b08Sjmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24cb5d4b08Sjmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25cb5d4b08Sjmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26cb5d4b08Sjmmv * POSSIBILITY OF SUCH DAMAGE.
27cb5d4b08Sjmmv */
28cb5d4b08Sjmmv
29cb5d4b08Sjmmv/* Originally written by David Wetzel */
30cb5d4b08Sjmmv
31cb5d4b08Sjmmv#include <assert.h>
32cb5d4b08Sjmmv#include <stdio.h>
33cb5d4b08Sjmmv#include <unistd.h>
34cb5d4b08Sjmmv
35cb5d4b08Sjmmv#include <atf-c.h>
36cb5d4b08Sjmmv
37cb5d4b08Sjmmv#include <objc/objc.h>
38*ddd5644bSchristos#include <objc/thr.h>
39cb5d4b08Sjmmv#include <objc/Object.h>
40*ddd5644bSchristos#if __GNUC_PREREQ__(4,8)
41*ddd5644bSchristos#include <objc/runtime.h>
42*ddd5644bSchristos#endif
43cb5d4b08Sjmmv
44cb5d4b08Sjmmvstatic int IsMultithreaded = 0;
45cb5d4b08Sjmmvstatic objc_mutex_t Mutex;
46cb5d4b08Sjmmvstatic objc_condition_t Condition;
47cb5d4b08Sjmmv
48cb5d4b08Sjmmv@interface MyClass : Object
49cb5d4b08Sjmmv{
50cb5d4b08Sjmmv}
51cb5d4b08Sjmmv-(void)start;
52*ddd5644bSchristos#if __GNUC_PREREQ__(4,8)
53*ddd5644bSchristos-init;
54*ddd5644bSchristos+new;
55*ddd5644bSchristos+alloc;
56*ddd5644bSchristos-free;
57*ddd5644bSchristos#endif
58cb5d4b08Sjmmv@end
59cb5d4b08Sjmmv
60cb5d4b08Sjmmv@implementation MyClass
61cb5d4b08Sjmmv-(void)start
62cb5d4b08Sjmmv{
63cb5d4b08Sjmmv	printf("detached thread started!\n");
64cb5d4b08Sjmmv
65cb5d4b08Sjmmv	objc_condition_signal(Condition);
66cb5d4b08Sjmmv}
67*ddd5644bSchristos#if __GNUC_PREREQ__(4,8)
68*ddd5644bSchristos-init
69*ddd5644bSchristos{
70*ddd5644bSchristos	return self;
71*ddd5644bSchristos}
72*ddd5644bSchristos
73*ddd5644bSchristos+new
74*ddd5644bSchristos{
75*ddd5644bSchristos	return [[self alloc] init];
76*ddd5644bSchristos}
77*ddd5644bSchristos
78*ddd5644bSchristos+alloc
79*ddd5644bSchristos{
80*ddd5644bSchristos	return class_createInstance(self, 0);
81*ddd5644bSchristos}
82*ddd5644bSchristos
83*ddd5644bSchristos-free
84*ddd5644bSchristos{
85*ddd5644bSchristos	return object_dispose(self);
86*ddd5644bSchristos}
87*ddd5644bSchristos#endif
88cb5d4b08Sjmmv@end
89cb5d4b08Sjmmv
90cb5d4b08Sjmmvstatic void
91cb5d4b08SjmmvbecomeMultiThreaded(void)
92cb5d4b08Sjmmv{
93cb5d4b08Sjmmv	printf("becoming multithreaded!\n");
94cb5d4b08Sjmmv	IsMultithreaded++;
95cb5d4b08Sjmmv}
96cb5d4b08Sjmmv
97cb5d4b08SjmmvATF_TC(thread_callback);
98cb5d4b08SjmmvATF_TC_HEAD(thread_callback, tc)
99cb5d4b08Sjmmv{
100cb5d4b08Sjmmv	atf_tc_set_md_var(tc, "descr", "Checks that the thread callback is only"
101cb5d4b08Sjmmv	    "called once");
102cb5d4b08Sjmmv}
103cb5d4b08SjmmvATF_TC_BODY(thread_callback, tc)
104cb5d4b08Sjmmv{
105cb5d4b08Sjmmv	id o = [MyClass new];
106cb5d4b08Sjmmv	objc_thread_callback cb;
107cb5d4b08Sjmmv	objc_thread_t rv;
108cb5d4b08Sjmmv
109cb5d4b08Sjmmv	cb = objc_set_thread_callback(becomeMultiThreaded);
110cb5d4b08Sjmmv	printf("Old Callback: %p\n", cb);
111cb5d4b08Sjmmv	ATF_CHECK(cb == 0);
112cb5d4b08Sjmmv
113cb5d4b08Sjmmv	Mutex = objc_mutex_allocate();
114cb5d4b08Sjmmv	Condition = objc_condition_allocate();
115cb5d4b08Sjmmv
116cb5d4b08Sjmmv	ATF_CHECK_EQ(0, IsMultithreaded);
117cb5d4b08Sjmmv
118cb5d4b08Sjmmv	rv = objc_thread_detach(@selector(start), o, nil);
119cb5d4b08Sjmmv	printf("detach value: %p\n", rv);
120cb5d4b08Sjmmv	assert(rv != NULL);
121cb5d4b08Sjmmv
122cb5d4b08Sjmmv	objc_mutex_lock(Mutex);
123cb5d4b08Sjmmv	objc_condition_wait(Condition, Mutex);
124cb5d4b08Sjmmv	objc_mutex_unlock(Mutex);
125cb5d4b08Sjmmv
126cb5d4b08Sjmmv	ATF_CHECK_EQ(1, IsMultithreaded);
127cb5d4b08Sjmmv	printf("Shutting down\n");
128cb5d4b08Sjmmv}
129cb5d4b08Sjmmv
130cb5d4b08SjmmvATF_TP_ADD_TCS(tp)
131cb5d4b08Sjmmv{
132cb5d4b08Sjmmv
133cb5d4b08Sjmmv	ATF_TP_ADD_TC(tp, thread_callback);
134cb5d4b08Sjmmv
135cb5d4b08Sjmmv	return atf_no_error();
136cb5d4b08Sjmmv}
137