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 */