1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://github.com/behlendorf/spl/>.
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting LAyer Tests (SPLAT) Thread Tests.
25 \*****************************************************************************/
27 #include "splat-internal.h"
29 #define SPLAT_THREAD_NAME "thread"
30 #define SPLAT_THREAD_DESC "Kernel Thread Tests"
32 #define SPLAT_THREAD_TEST1_ID 0x0601
33 #define SPLAT_THREAD_TEST1_NAME "create"
34 #define SPLAT_THREAD_TEST1_DESC "Validate thread creation"
36 #define SPLAT_THREAD_TEST2_ID 0x0602
37 #define SPLAT_THREAD_TEST2_NAME "exit"
38 #define SPLAT_THREAD_TEST2_DESC "Validate thread exit"
40 #define SPLAT_THREAD_TEST_MAGIC 0x4488CC00UL
42 typedef struct thread_priv
{
43 unsigned long tp_magic
;
46 wait_queue_head_t tp_waitq
;
51 splat_thread_rc(thread_priv_t
*tp
, int rc
)
55 spin_lock(&tp
->tp_lock
);
56 ret
= (tp
->tp_rc
== rc
);
57 spin_unlock(&tp
->tp_lock
);
63 splat_thread_work1(void *priv
)
65 thread_priv_t
*tp
= (thread_priv_t
*)priv
;
67 spin_lock(&tp
->tp_lock
);
68 ASSERT(tp
->tp_magic
== SPLAT_THREAD_TEST_MAGIC
);
70 wake_up(&tp
->tp_waitq
);
71 spin_unlock(&tp
->tp_lock
);
77 splat_thread_test1(struct file
*file
, void *arg
)
82 tp
.tp_magic
= SPLAT_THREAD_TEST_MAGIC
;
84 spin_lock_init(&tp
.tp_lock
);
85 init_waitqueue_head(&tp
.tp_waitq
);
88 thr
= (kthread_t
*)thread_create(NULL
, 0, splat_thread_work1
, &tp
, 0,
89 &p0
, TS_RUN
, minclsyspri
);
90 /* Must never fail under Solaris, but we check anyway since this
91 * can happen in the linux SPL, we may want to change this behavior */
95 /* Sleep until the thread sets tp.tp_rc == 1 */
96 wait_event(tp
.tp_waitq
, splat_thread_rc(&tp
, 1));
98 splat_vprint(file
, SPLAT_THREAD_TEST1_NAME
, "%s",
99 "Thread successfully started properly\n");
104 splat_thread_work2(void *priv
)
106 thread_priv_t
*tp
= (thread_priv_t
*)priv
;
108 spin_lock(&tp
->tp_lock
);
109 ASSERT(tp
->tp_magic
== SPLAT_THREAD_TEST_MAGIC
);
111 wake_up(&tp
->tp_waitq
);
112 spin_unlock(&tp
->tp_lock
);
116 /* The following code is unreachable when thread_exit() is
117 * working properly, which is exactly what we're testing */
118 spin_lock(&tp
->tp_lock
);
120 wake_up(&tp
->tp_waitq
);
121 spin_unlock(&tp
->tp_lock
);
125 splat_thread_test2(struct file
*file
, void *arg
)
131 tp
.tp_magic
= SPLAT_THREAD_TEST_MAGIC
;
133 spin_lock_init(&tp
.tp_lock
);
134 init_waitqueue_head(&tp
.tp_waitq
);
137 thr
= (kthread_t
*)thread_create(NULL
, 0, splat_thread_work2
, &tp
, 0,
138 &p0
, TS_RUN
, minclsyspri
);
139 /* Must never fail under Solaris, but we check anyway since this
140 * can happen in the linux SPL, we may want to change this behavior */
144 /* Sleep until the thread sets tp.tp_rc == 1 */
145 wait_event(tp
.tp_waitq
, splat_thread_rc(&tp
, 1));
147 /* Sleep until the thread sets tp.tp_rc == 2, or until we hit
148 * the timeout. If thread exit is working properly we should
149 * hit the timeout and never see to.tp_rc == 2. */
150 rc
= wait_event_timeout(tp
.tp_waitq
, splat_thread_rc(&tp
, 2), HZ
/ 10);
153 splat_vprint(file
, SPLAT_THREAD_TEST2_NAME
, "%s",
154 "Thread did not exit properly at thread_exit()\n");
156 splat_vprint(file
, SPLAT_THREAD_TEST2_NAME
, "%s",
157 "Thread successfully exited at thread_exit()\n");
164 splat_thread_init(void)
166 splat_subsystem_t
*sub
;
168 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
172 memset(sub
, 0, sizeof(*sub
));
173 strncpy(sub
->desc
.name
, SPLAT_THREAD_NAME
, SPLAT_NAME_SIZE
);
174 strncpy(sub
->desc
.desc
, SPLAT_THREAD_DESC
, SPLAT_DESC_SIZE
);
175 INIT_LIST_HEAD(&sub
->subsystem_list
);
176 INIT_LIST_HEAD(&sub
->test_list
);
177 spin_lock_init(&sub
->test_lock
);
178 sub
->desc
.id
= SPLAT_SUBSYSTEM_THREAD
;
180 SPLAT_TEST_INIT(sub
, SPLAT_THREAD_TEST1_NAME
, SPLAT_THREAD_TEST1_DESC
,
181 SPLAT_THREAD_TEST1_ID
, splat_thread_test1
);
182 SPLAT_TEST_INIT(sub
, SPLAT_THREAD_TEST2_NAME
, SPLAT_THREAD_TEST2_DESC
,
183 SPLAT_THREAD_TEST2_ID
, splat_thread_test2
);
189 splat_thread_fini(splat_subsystem_t
*sub
)
192 SPLAT_TEST_FINI(sub
, SPLAT_THREAD_TEST2_ID
);
193 SPLAT_TEST_FINI(sub
, SPLAT_THREAD_TEST1_ID
);
199 splat_thread_id(void) {
200 return SPLAT_SUBSYSTEM_THREAD
;