1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
14  * Copyright 2018 RackTop Systems.
15  */
16 
17 #include <sys/cmn_err.h>
18 #include <sys/thread.h>
19 #include <sys/zone.h>
20 #include <sys/proc.h>
21 #include <sys/atomic.h>
22 
23 #define	_SYNCH_H	/* keep out <synch.h> */
24 #include <thread.h>
25 
26 /*
27  * Get the current kthread_t pointer.
28  */
29 kthread_t *
_curthread(void)30 _curthread(void)
31 {
32 	thread_t tid;
33 
34 	tid = thr_self();
35 	return ((kthread_t *)(uintptr_t)tid);
36 }
37 
38 /*
39  * Create a thread.
40  *
41  * thread_create() blocks for memory if necessary.  It never fails.
42  */
43 /* ARGSUSED */
44 kthread_t *
thread_create(caddr_t stk,size_t stksize,void (* func)(),void * arg,size_t len,struct proc * pp,int state,pri_t pri)45 thread_create(
46 	caddr_t	stk,
47 	size_t	stksize,
48 	void	(*func)(),
49 	void	*arg,
50 	size_t	len,
51 	struct proc *pp,
52 	int	state,
53 	pri_t	pri)
54 {
55 	void * (*thr_func)(void *);
56 	thread_t newtid;
57 	int thr_flags = 0;
58 	int rc;
59 
60 	thr_flags = THR_BOUND;
61 
62 	switch (state) {
63 	case TS_RUN:
64 	case TS_ONPROC:
65 		break;
66 	case TS_STOPPED:
67 		thr_flags |= THR_SUSPENDED;
68 		break;
69 	default:
70 		cmn_err(CE_PANIC, "thread_create: invalid state");
71 		break;
72 	}
73 
74 	thr_func = (void *(*)(void *))(uintptr_t)func;
75 	rc = thr_create(NULL, 0, thr_func, arg, thr_flags, &newtid);
76 	if (rc != 0)
77 		cmn_err(CE_PANIC, "thread_create failed, rc=%d", rc);
78 
79 	return ((void *)(uintptr_t)newtid);
80 }
81 
82 void
thread_exit(void)83 thread_exit(void)
84 {
85 	static thread_t reap_tid;
86 	thread_t prev;
87 
88 	/* reap previous thread exit */
89 	prev = atomic_swap_uint(&reap_tid, thr_self());
90 	if (prev != 0)
91 		(void) thr_join(prev, NULL, NULL); /* joinable thread */
92 
93 	thr_exit(NULL);
94 }
95 
96 void
thread_join(kt_did_t id)97 thread_join(kt_did_t id)
98 {
99 	thread_t thr_id;
100 
101 	thr_id = (thread_t)id;
102 	(void) thr_join(thr_id, NULL, NULL);
103 }
104 
105 void
tsignal(kthread_t * kt,int sig)106 tsignal(kthread_t *kt, int sig)
107 {
108 	thread_t tid = (thread_t)(uintptr_t)kt;
109 
110 	(void) thr_kill(tid, sig);
111 }
112 
113 
114 /*ARGSUSED*/
115 kthread_t *
zthread_create(caddr_t stk,size_t stksize,void (* func)(),void * arg,size_t len,pri_t pri)116 zthread_create(
117     caddr_t stk,
118     size_t stksize,
119     void (*func)(),
120     void *arg,
121     size_t len,
122     pri_t pri)
123 {
124 	kthread_t *t;
125 
126 	t = thread_create(stk, stksize, func, arg, len, NULL, TS_RUN, pri);
127 
128 	return (t);
129 }
130 
131 void
zthread_exit(void)132 zthread_exit(void)
133 {
134 	thread_exit();
135 	/* NOTREACHED */
136 }
137 
138 void
tsd_create(uint_t * keyp,void (* destructor)(void *))139 tsd_create(uint_t *keyp, void (*destructor)(void *))
140 {
141 	VERIFY0(thr_keycreate(keyp, destructor));
142 }
143 
144 /*ARGSUSED*/
145 void
tsd_destroy(uint_t * keyp)146 tsd_destroy(uint_t *keyp)
147 {}
148 
149 void *
tsd_get(uint_t key)150 tsd_get(uint_t key)
151 {
152 	void *value;
153 
154 	return (thr_getspecific(key, &value) ? NULL : value);
155 }
156 
157 int
tsd_set(uint_t key,void * value)158 tsd_set(uint_t key, void *value)
159 {
160 	return (thr_setspecific(key, value));
161 }
162