| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pthread_int.h,v 1.99 2020/01/27 20:50:05 ad Exp $ */ | | 1 | /* $NetBSD: pthread_int.h,v 1.100 2020/01/28 13:08:40 ad Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 | | 4 | * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 |
5 | * The NetBSD Foundation, Inc. | | 5 | * The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Nathan J. Williams and Andrew Doran. | | 9 | * by Nathan J. Williams and Andrew Doran. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -37,26 +37,27 @@ | | | @@ -37,26 +37,27 @@ |
37 | | | 37 | |
38 | /* #define PTHREAD__DEBUG */ | | 38 | /* #define PTHREAD__DEBUG */ |
39 | #define ERRORCHECK | | 39 | #define ERRORCHECK |
40 | | | 40 | |
41 | #include "pthread_types.h" | | 41 | #include "pthread_types.h" |
42 | #include "pthread_queue.h" | | 42 | #include "pthread_queue.h" |
43 | #include "pthread_md.h" | | 43 | #include "pthread_md.h" |
44 | | | 44 | |
45 | /* Need to use libc-private names for atomic operations. */ | | 45 | /* Need to use libc-private names for atomic operations. */ |
46 | #include "../../common/lib/libc/atomic/atomic_op_namespace.h" | | 46 | #include "../../common/lib/libc/atomic/atomic_op_namespace.h" |
47 | | | 47 | |
48 | #include <sys/atomic.h> | | 48 | #include <sys/atomic.h> |
49 | #include <sys/rbtree.h> | | 49 | #include <sys/rbtree.h> |
| | | 50 | #include <sys/param.h> |
50 | | | 51 | |
51 | #include <limits.h> | | 52 | #include <limits.h> |
52 | #include <lwp.h> | | 53 | #include <lwp.h> |
53 | #include <signal.h> | | 54 | #include <signal.h> |
54 | #include <stdbool.h> | | 55 | #include <stdbool.h> |
55 | | | 56 | |
56 | #ifdef __GNUC__ | | 57 | #ifdef __GNUC__ |
57 | #define PTHREAD_HIDE __attribute__ ((visibility("hidden"))) | | 58 | #define PTHREAD_HIDE __attribute__ ((visibility("hidden"))) |
58 | #else | | 59 | #else |
59 | #define PTHREAD_HIDE /* nothing */ | | 60 | #define PTHREAD_HIDE /* nothing */ |
60 | #endif | | 61 | #endif |
61 | | | 62 | |
62 | #define PTHREAD__UNPARK_MAX 128 | | 63 | #define PTHREAD__UNPARK_MAX 128 |
| @@ -86,71 +87,79 @@ struct pthread_lock_ops { | | | @@ -86,71 +87,79 @@ struct pthread_lock_ops { |
86 | void (*plo_init)(__cpu_simple_lock_t *); | | 87 | void (*plo_init)(__cpu_simple_lock_t *); |
87 | int (*plo_try)(__cpu_simple_lock_t *); | | 88 | int (*plo_try)(__cpu_simple_lock_t *); |
88 | void (*plo_unlock)(__cpu_simple_lock_t *); | | 89 | void (*plo_unlock)(__cpu_simple_lock_t *); |
89 | void (*plo_lock)(__cpu_simple_lock_t *); | | 90 | void (*plo_lock)(__cpu_simple_lock_t *); |
90 | }; | | 91 | }; |
91 | | | 92 | |
92 | struct __pthread_st { | | 93 | struct __pthread_st { |
93 | pthread_t pt_self; /* Must be first. */ | | 94 | pthread_t pt_self; /* Must be first. */ |
94 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) | | 95 | #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) |
95 | struct tls_tcb *pt_tls; /* Thread Local Storage area */ | | 96 | struct tls_tcb *pt_tls; /* Thread Local Storage area */ |
96 | #endif | | 97 | #endif |
97 | unsigned int pt_magic; /* Magic number */ | | 98 | unsigned int pt_magic; /* Magic number */ |
98 | int pt_state; /* running, blocked, etc. */ | | 99 | int pt_state; /* running, blocked, etc. */ |
99 | pthread_mutex_t pt_lock; /* lock on state */ | | | |
100 | int pt_flags; /* see PT_FLAG_* below */ | | 100 | int pt_flags; /* see PT_FLAG_* below */ |
101 | int pt_cancel; /* Deferred cancellation */ | | 101 | int pt_cancel; /* Deferred cancellation */ |
102 | int pt_errno; /* Thread-specific errno. */ | | 102 | int pt_errno; /* Thread-specific errno. */ |
103 | stack_t pt_stack; /* Our stack */ | | 103 | stack_t pt_stack; /* Our stack */ |
104 | bool pt_stack_allocated; | | 104 | bool pt_stack_allocated; |
105 | size_t pt_guardsize; | | 105 | size_t pt_guardsize; |
106 | void *pt_exitval; /* Read by pthread_join() */ | | 106 | void *pt_exitval; /* Read by pthread_join() */ |
107 | char *pt_name; /* Thread's name, set by the app. */ | | 107 | char *pt_name; /* Thread's name, set by the app. */ |
108 | int pt_willpark; /* About to park */ | | 108 | int pt_willpark; /* About to park */ |
109 | lwpid_t pt_unpark; /* Unpark this when parking */ | | 109 | lwpid_t pt_unpark; /* Unpark this when parking */ |
110 | struct pthread_lock_ops pt_lockops;/* Cached to avoid PIC overhead */ | | 110 | struct pthread_lock_ops pt_lockops;/* Cached to avoid PIC overhead */ |
111 | void *(*pt_func)(void *);/* Function to call at start. */ | | 111 | void *(*pt_func)(void *);/* Function to call at start. */ |
112 | void *pt_arg; /* Argument to pass at start. */ | | 112 | void *pt_arg; /* Argument to pass at start. */ |
113 | | | 113 | |
114 | /* Threads to defer waking, usually until pthread_mutex_unlock(). */ | | 114 | /* Threads to defer waking, usually until pthread_mutex_unlock(). */ |
115 | lwpid_t pt_waiters[PTHREAD__UNPARK_MAX]; | | 115 | lwpid_t pt_waiters[PTHREAD__UNPARK_MAX]; |
116 | size_t pt_nwaiters; | | 116 | size_t pt_nwaiters; |
117 | | | 117 | |
118 | /* Stack of cancellation cleanup handlers and their arguments */ | | 118 | /* Stack of cancellation cleanup handlers and their arguments */ |
119 | PTQ_HEAD(, pt_clean_t) pt_cleanup_stack; | | 119 | PTQ_HEAD(, pt_clean_t) pt_cleanup_stack; |
120 | | | 120 | |
121 | /* LWP ID and entry on the list of all threads. */ | | 121 | /* LWP ID and entry on the list of all threads. */ |
122 | lwpid_t pt_lid; | | 122 | lwpid_t pt_lid; |
123 | rb_node_t pt_alltree; | | | |
124 | PTQ_ENTRY(__pthread_st) pt_allq; | | | |
125 | PTQ_ENTRY(__pthread_st) pt_deadq; | | 123 | PTQ_ENTRY(__pthread_st) pt_deadq; |
126 | | | 124 | |
127 | /* | | 125 | /* |
| | | 126 | * rbtree node and entry on the list of all threads. pt_alltree in |
| | | 127 | * its own cacheline, so pthread__find() is not needlessly impacted |
| | | 128 | * by threads going about their normal business. pt_allq is |
| | | 129 | * adjusted at the same time as pt_alltree. |
| | | 130 | */ |
| | | 131 | rb_node_t pt_alltree __aligned(COHERENCY_UNIT); |
| | | 132 | PTQ_ENTRY(__pthread_st) pt_allq; |
| | | 133 | |
| | | 134 | /* Lock on state also gets its own line. */ |
| | | 135 | pthread_mutex_t pt_lock __aligned(COHERENCY_UNIT); |
| | | 136 | |
| | | 137 | /* |
128 | * General synchronization data. We try to align, as threads | | 138 | * General synchronization data. We try to align, as threads |
129 | * on other CPUs will access this data frequently. | | 139 | * on other CPUs will access this data frequently. |
130 | */ | | 140 | */ |
131 | int pt_dummy1 __aligned(128); | | 141 | int pt_dummy1 __aligned(COHERENCY_UNIT); |
132 | struct lwpctl *pt_lwpctl; /* Kernel/user comms area */ | | 142 | struct lwpctl *pt_lwpctl; /* Kernel/user comms area */ |
133 | volatile int pt_rwlocked; /* Handed rwlock successfully */ | | 143 | volatile int pt_rwlocked; /* Handed rwlock successfully */ |
134 | volatile int pt_signalled; /* Received pthread_cond_signal() */ | | 144 | volatile int pt_signalled; /* Received pthread_cond_signal() */ |
135 | volatile int pt_mutexwait; /* Waiting to acquire mutex */ | | 145 | volatile int pt_mutexwait; /* Waiting to acquire mutex */ |
136 | void * volatile pt_mutexnext; /* Next thread in chain */ | | 146 | void * volatile pt_mutexnext; /* Next thread in chain */ |
137 | void * volatile pt_sleepobj; /* Object slept on */ | | 147 | void * volatile pt_sleepobj; /* Object slept on */ |
138 | PTQ_ENTRY(__pthread_st) pt_sleep; | | 148 | PTQ_ENTRY(__pthread_st) pt_sleep; |
139 | void (*pt_early)(void *); | | 149 | void (*pt_early)(void *); |
140 | int pt_dummy2 __aligned(128); | | | |
141 | | | 150 | |
142 | /* Thread-specific data. Large so it sits close to the end. */ | | 151 | /* Thread-specific data. Large so it sits close to the end. */ |
143 | int pt_havespecific; | | 152 | int pt_havespecific __aligned(COHERENCY_UNIT); |
144 | struct pt_specific { | | 153 | struct pt_specific { |
145 | void *pts_value; | | 154 | void *pts_value; |
146 | PTQ_ENTRY(pt_specific) pts_next; | | 155 | PTQ_ENTRY(pt_specific) pts_next; |
147 | } pt_specific[]; | | 156 | } pt_specific[]; |
148 | }; | | 157 | }; |
149 | | | 158 | |
150 | /* Thread states */ | | 159 | /* Thread states */ |
151 | #define PT_STATE_RUNNING 1 | | 160 | #define PT_STATE_RUNNING 1 |
152 | #define PT_STATE_ZOMBIE 5 | | 161 | #define PT_STATE_ZOMBIE 5 |
153 | #define PT_STATE_DEAD 6 | | 162 | #define PT_STATE_DEAD 6 |
154 | | | 163 | |
155 | /* Flag values */ | | 164 | /* Flag values */ |
156 | | | 165 | |