Mercurial > hg > nginx
comparison src/os/unix/ngx_freebsd_rfork_thread.c @ 272:d4e65d74db9f
nginx-0.0.2-2004-03-01-00:03:02 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 29 Feb 2004 21:03:02 +0000 |
parents | e16dfb9b9afa |
children | 4b1a3a4acc60 |
comparison
equal
deleted
inserted
replaced
271:e16dfb9b9afa | 272:d4e65d74db9f |
---|---|
1 | |
2 /* | |
3 * Copyright (C) 2002-2004 Igor Sysoev, http://sysoev.ru/en/ | |
4 */ | |
5 | |
1 | 6 |
2 #include <ngx_config.h> | 7 #include <ngx_config.h> |
3 #include <ngx_core.h> | 8 #include <ngx_core.h> |
4 | 9 |
5 /* | 10 /* |
19 * This threads implementation currently works on i486 and amd64 | 24 * This threads implementation currently works on i486 and amd64 |
20 * platforms only. | 25 * platforms only. |
21 */ | 26 */ |
22 | 27 |
23 | 28 |
24 ngx_int_t ngx_threaded; | 29 ngx_int_t ngx_threaded; |
25 | 30 char *ngx_freebsd_kern_usrstack; |
26 static inline int ngx_gettid(); | 31 size_t ngx_thread_stack_size; |
27 | 32 |
28 | 33 |
29 static char *usrstack; | |
30 static size_t rz_size = /* STUB: PAGE_SIZE */ 4096; | 34 static size_t rz_size = /* STUB: PAGE_SIZE */ 4096; |
31 | |
32 static size_t stack_size; | |
33 static size_t usable_stack_size; | 35 static size_t usable_stack_size; |
34 static char *last_stack; | 36 static char *last_stack; |
35 | 37 |
36 static ngx_uint_t nthreads; | 38 static ngx_uint_t nthreads; |
37 static ngx_uint_t max_threads; | 39 static ngx_uint_t max_threads; |
52 return tid ? &errnos[tid - 1] : &errno0; | 54 return tid ? &errnos[tid - 1] : &errno0; |
53 } | 55 } |
54 | 56 |
55 | 57 |
56 /* | 58 /* |
57 * __isthreaded enables spinlock() in some libc functions, i.e. in malloc() | 59 * __isthreaded enables the spinlocks in some libc functions, i.e. in malloc() |
58 * and some other places. Nevertheless we protect our malloc()/free() calls | 60 * and some other places. Nevertheless we protect our malloc()/free() calls |
59 * by own mutex that is more efficient than the spinlock. | 61 * by own mutex that is more efficient than the spinlock. |
60 * | 62 * |
61 * We define own _spinlock() because a weak referenced _spinlock() stub in | 63 * _spinlock() is a weak referenced stub in src/lib/libc/gen/_spinlock_stub.c |
62 * src/lib/libc/gen/_spinlock_stub.c does nothing. | 64 * that does nothing. |
63 */ | 65 */ |
64 | 66 |
65 extern int __isthreaded; | 67 extern int __isthreaded; |
66 | 68 |
67 void _spinlock(ngx_atomic_t *lock) | 69 void _spinlock(ngx_atomic_t *lock) |
68 { | 70 { |
69 ngx_int_t tries; | 71 ngx_int_t tries; |
70 | 72 |
71 tries = 0; | 73 tries = 0; |
74 | |
72 for ( ;; ) { | 75 for ( ;; ) { |
73 | 76 |
74 if (*lock) { | 77 if (*lock) { |
75 if (ngx_freebsd_hw_ncpu > 1 && tries++ < 1000) { | 78 if (ngx_freebsd_hw_ncpu > 1 && tries++ < 1000) { |
76 continue; | 79 continue; |
86 } | 89 } |
87 } | 90 } |
88 } | 91 } |
89 | 92 |
90 | 93 |
94 /* | |
95 * Before FreeBSD 5.1 _spinunlock() is a simple #define in | |
96 * src/lib/libc/include/spinlock.h that zeroes lock. | |
97 * | |
98 * Since FreeBSD 5.1 _spinunlock() is a weak referenced stub in | |
99 * src/lib/libc/gen/_spinlock_stub.c that does nothing. | |
100 */ | |
101 | |
102 #ifndef _spinunlock | |
103 | |
104 void _spinunlock(ngx_atomic_t *lock) | |
105 { | |
106 *lock = 0; | |
107 } | |
108 | |
109 #endif | |
110 | |
111 | |
91 int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg, | 112 int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg, |
92 ngx_log_t *log) | 113 ngx_log_t *log) |
93 { | 114 { |
94 int id, err; | 115 int id, err; |
95 char *stack, *stack_top; | 116 char *stack, *stack_top; |
98 ngx_log_error(NGX_LOG_CRIT, log, 0, | 119 ngx_log_error(NGX_LOG_CRIT, log, 0, |
99 "no more than %d threads can be created", max_threads); | 120 "no more than %d threads can be created", max_threads); |
100 return NGX_ERROR; | 121 return NGX_ERROR; |
101 } | 122 } |
102 | 123 |
103 last_stack -= stack_size; | 124 last_stack -= ngx_thread_stack_size; |
104 | 125 |
105 stack = mmap(last_stack, usable_stack_size, PROT_READ|PROT_WRITE, | 126 stack = mmap(last_stack, usable_stack_size, PROT_READ|PROT_WRITE, |
106 MAP_STACK, -1, 0); | 127 MAP_STACK, -1, 0); |
107 | 128 |
108 if (stack == MAP_FAILED) { | 129 if (stack == MAP_FAILED) { |
137 if (id == -1) { | 158 if (id == -1) { |
138 ngx_log_error(NGX_LOG_ALERT, log, err, "rfork() failed"); | 159 ngx_log_error(NGX_LOG_ALERT, log, err, "rfork() failed"); |
139 | 160 |
140 } else { | 161 } else { |
141 *tid = id; | 162 *tid = id; |
142 nthreads = (usrstack - stack_top) / stack_size; | 163 nthreads = (ngx_freebsd_kern_usrstack - stack_top) |
164 / ngx_thread_stack_size; | |
143 tids[nthreads] = id; | 165 tids[nthreads] = id; |
144 | 166 |
145 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "rfork()ed thread: %d", id); | 167 ngx_log_debug1(NGX_LOG_DEBUG_CORE, log, 0, "rfork()ed thread: %d", id); |
146 } | 168 } |
147 | 169 |
154 size_t len; | 176 size_t len; |
155 char *red_zone, *zone; | 177 char *red_zone, *zone; |
156 | 178 |
157 max_threads = n; | 179 max_threads = n; |
158 | 180 |
159 len = sizeof(usrstack); | 181 len = sizeof(ngx_freebsd_kern_usrstack); |
160 if (sysctlbyname("kern.usrstack", &usrstack, &len, NULL, 0) == -1) { | 182 if (sysctlbyname("kern.usrstack", &ngx_freebsd_kern_usrstack, &len, |
183 NULL, 0) == -1) | |
184 { | |
161 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 185 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
162 "sysctlbyname(kern.usrstack) failed"); | 186 "sysctlbyname(kern.usrstack) failed"); |
163 return NGX_ERROR; | 187 return NGX_ERROR; |
164 } | 188 } |
165 | 189 |
166 /* the main thread stack red zone */ | 190 /* the main thread stack red zone */ |
167 red_zone = usrstack - (size + rz_size); | 191 red_zone = ngx_freebsd_kern_usrstack - (size + rz_size); |
168 | 192 |
169 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, | 193 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, |
170 "usrstack: " PTR_FMT " red zone: " PTR_FMT, | 194 "usrstack: " PTR_FMT " red zone: " PTR_FMT, |
171 usrstack, red_zone); | 195 ngx_freebsd_kern_usrstack, red_zone); |
172 | 196 |
173 zone = mmap(red_zone, rz_size, PROT_NONE, MAP_ANON, -1, 0); | 197 zone = mmap(red_zone, rz_size, PROT_NONE, MAP_ANON, -1, 0); |
174 if (zone == MAP_FAILED) { | 198 if (zone == MAP_FAILED) { |
175 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 199 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
176 "mmap(" PTR_FMT ":" SIZE_T_FMT | 200 "mmap(" PTR_FMT ":" SIZE_T_FMT |
199 tids[0] = ngx_pid; | 223 tids[0] = ngx_pid; |
200 nthreads = 1; | 224 nthreads = 1; |
201 | 225 |
202 last_stack = zone + rz_size; | 226 last_stack = zone + rz_size; |
203 usable_stack_size = size; | 227 usable_stack_size = size; |
204 stack_size = size + rz_size; | 228 ngx_thread_stack_size = size + rz_size; |
205 | 229 |
206 /* allow the spinlock in libc malloc() */ | 230 /* allow the spinlock in libc malloc() */ |
207 __isthreaded = 1; | 231 __isthreaded = 1; |
208 | 232 |
209 ngx_threaded = 1; | 233 ngx_threaded = 1; |
210 | 234 |
211 return NGX_OK; | 235 return NGX_OK; |
212 } | |
213 | |
214 | |
215 static inline int ngx_gettid() | |
216 { | |
217 char *sp; | |
218 | |
219 if (stack_size == 0) { | |
220 return 0; | |
221 } | |
222 | |
223 #if ( __i386__ ) | |
224 | |
225 __asm__ volatile ("mov %%esp, %0" : "=q" (sp)); | |
226 | |
227 #elif ( __amd64__ ) | |
228 | |
229 __asm__ volatile ("mov %%rsp, %0" : "=q" (sp)); | |
230 | |
231 #endif | |
232 | |
233 return (usrstack - sp) / stack_size; | |
234 } | 236 } |
235 | 237 |
236 | 238 |
237 ngx_tid_t ngx_thread_self() | 239 ngx_tid_t ngx_thread_self() |
238 { | 240 { |
311 | 313 |
312 ngx_free((void *) m); | 314 ngx_free((void *) m); |
313 } | 315 } |
314 | 316 |
315 | 317 |
316 ngx_int_t ngx_mutex_do_lock(ngx_mutex_t *m, ngx_int_t try) | 318 ngx_int_t ngx_mutex_dolock(ngx_mutex_t *m, ngx_int_t try) |
317 { | 319 { |
318 uint32_t lock, new, old; | 320 uint32_t lock, new, old; |
319 ngx_uint_t tries; | 321 ngx_uint_t tries; |
320 struct sembuf op; | 322 struct sembuf op; |
321 | 323 |
451 } | 453 } |
452 | 454 |
453 old = m->lock; | 455 old = m->lock; |
454 | 456 |
455 if (!(old & NGX_MUTEX_LOCK_BUSY)) { | 457 if (!(old & NGX_MUTEX_LOCK_BUSY)) { |
456 ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno, | 458 ngx_log_error(NGX_LOG_ALERT, m->log, 0, |
457 "tring to unlock the free mutex " PTR_FMT, m); | 459 "tring to unlock the free mutex " PTR_FMT, m); |
458 return NGX_ERROR; | 460 return NGX_ERROR; |
459 } | 461 } |
460 | 462 |
461 /* free the mutex */ | 463 /* free the mutex */ |