xref: /netbsd-src/lib/libpthread/pthread_specific.c (revision 568eb77ef2a2b1fbe2457d69c7aa6e1dd3d8de8b)
1*568eb77eSriastradh /*	$NetBSD: pthread_specific.c,v 1.28 2022/04/10 10:38:33 riastradh Exp $	*/
2c62a74e6Sthorpej 
3c62a74e6Sthorpej /*-
4b8833ff5Sad  * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
5c62a74e6Sthorpej  * All rights reserved.
6c62a74e6Sthorpej  *
7c62a74e6Sthorpej  * This code is derived from software contributed to The NetBSD Foundation
8c62a74e6Sthorpej  * by Nathan J. Williams.
9c62a74e6Sthorpej  *
10c62a74e6Sthorpej  * Redistribution and use in source and binary forms, with or without
11c62a74e6Sthorpej  * modification, are permitted provided that the following conditions
12c62a74e6Sthorpej  * are met:
13c62a74e6Sthorpej  * 1. Redistributions of source code must retain the above copyright
14c62a74e6Sthorpej  *    notice, this list of conditions and the following disclaimer.
15c62a74e6Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
16c62a74e6Sthorpej  *    notice, this list of conditions and the following disclaimer in the
17c62a74e6Sthorpej  *    documentation and/or other materials provided with the distribution.
18c62a74e6Sthorpej  *
19c62a74e6Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20c62a74e6Sthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21c62a74e6Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22c62a74e6Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23c62a74e6Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24c62a74e6Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25c62a74e6Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26c62a74e6Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27c62a74e6Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28c62a74e6Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29c62a74e6Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
30c62a74e6Sthorpej  */
31c62a74e6Sthorpej 
32f043c0fbSlukem #include <sys/cdefs.h>
33*568eb77eSriastradh __RCSID("$NetBSD: pthread_specific.c,v 1.28 2022/04/10 10:38:33 riastradh Exp $");
347adb4107Sriastradh 
357adb4107Sriastradh /* Need to use libc-private names for atomic operations. */
367adb4107Sriastradh #include "../../common/lib/libc/atomic/atomic_op_namespace.h"
37f043c0fbSlukem 
38c62a74e6Sthorpej /* Functions and structures dealing with thread-specific data */
39c62a74e6Sthorpej 
40c62a74e6Sthorpej #include "pthread.h"
41c62a74e6Sthorpej #include "pthread_int.h"
4271d484f9Schristos #include "reentrant.h"
43c62a74e6Sthorpej 
44bba80928Smanu #include <string.h>
454084ca7fSad #include <sys/lwpctl.h>
464084ca7fSad 
47bba80928Smanu #include "../libc/include/extern.h" /* for _sys_setcontext() */
48bba80928Smanu 
49bba80928Smanu int	pthread_setcontext(const ucontext_t *);
50bba80928Smanu 
__strong_alias(__libc_thr_setspecific,pthread_setspecific)51c62a74e6Sthorpej __strong_alias(__libc_thr_setspecific,pthread_setspecific)
52c62a74e6Sthorpej __strong_alias(__libc_thr_getspecific,pthread_getspecific)
534084ca7fSad __strong_alias(__libc_thr_curcpu,pthread_curcpu_np)
54c62a74e6Sthorpej 
55bba80928Smanu __strong_alias(setcontext,pthread_setcontext)
56bba80928Smanu 
57c62a74e6Sthorpej int
58c62a74e6Sthorpej pthread_setspecific(pthread_key_t key, const void *value)
59c62a74e6Sthorpej {
60c62a74e6Sthorpej 	pthread_t self;
61c62a74e6Sthorpej 
6271d484f9Schristos 	if (__predict_false(__uselibcstub))
6371d484f9Schristos 		return __libc_thr_setspecific_stub(key, value);
6471d484f9Schristos 
65c62a74e6Sthorpej 	self = pthread__self();
66c62a74e6Sthorpej 	/*
67c62a74e6Sthorpej 	 * We can't win here on constness. Having been given a
68c62a74e6Sthorpej 	 * "const void *", we can only assign it to other const void *,
69c62a74e6Sthorpej 	 * and return it from functions that are const void *, without
70c62a74e6Sthorpej 	 * generating a warning.
71c62a74e6Sthorpej 	 */
7255f47ec3Schristos 	return pthread__add_specific(self, key, value);
73c62a74e6Sthorpej }
74c62a74e6Sthorpej 
75c62a74e6Sthorpej void *
pthread_getspecific(pthread_key_t key)76c62a74e6Sthorpej pthread_getspecific(pthread_key_t key)
77c62a74e6Sthorpej {
7871d484f9Schristos 	if (__predict_false(__uselibcstub))
7971d484f9Schristos 		return __libc_thr_getspecific_stub(key);
804084ca7fSad 
8155f47ec3Schristos 	return pthread__self()->pt_specific[key].pts_value;
82c62a74e6Sthorpej }
834084ca7fSad 
844084ca7fSad unsigned int
pthread_curcpu_np(void)854084ca7fSad pthread_curcpu_np(void)
864084ca7fSad {
8771d484f9Schristos 	if (__predict_false(__uselibcstub))
8871d484f9Schristos 		return __libc_thr_curcpu_stub();
8971d484f9Schristos 
9071d484f9Schristos 	{
9193af5b69Syamt 		const int curcpu = pthread__self()->pt_lwpctl->lc_curcpu;
9248a1e4cfSyamt 
9393af5b69Syamt 		pthread__assert(curcpu != LWPCTL_CPU_NONE);
9493af5b69Syamt 		pthread__assert(curcpu != LWPCTL_CPU_EXITED);
9593af5b69Syamt 		pthread__assert(curcpu >= 0);
9693af5b69Syamt 		return curcpu;
974084ca7fSad 	}
9871d484f9Schristos }
99bba80928Smanu 
100bba80928Smanu /*
101bba80928Smanu  * Override setcontext so that pthread private pointer is preserved
102bba80928Smanu  */
103bba80928Smanu int
pthread_setcontext(const ucontext_t * ucp)104bba80928Smanu pthread_setcontext(const ucontext_t *ucp)
105bba80928Smanu {
106426a7619Smatt #ifdef _UC_TLSBASE
107bba80928Smanu 	ucontext_t uc;
108426a7619Smatt 	/*
109426a7619Smatt 	 * Only copy and clear _UC_TLSBASE if it is set.
110426a7619Smatt 	 */
111426a7619Smatt 	if (ucp->uc_flags & _UC_TLSBASE) {
112426a7619Smatt 		uc = *ucp;
113bba80928Smanu 		uc.uc_flags &= ~_UC_TLSBASE;
114426a7619Smatt 		ucp = &uc;
115426a7619Smatt 	}
116426a7619Smatt #endif /* _UC_TLSBASE */
117426a7619Smatt 	return _sys_setcontext(ucp);
118bba80928Smanu }
119