Mercurial > hg > nginx-quic
comparison src/os/unix/ngx_freebsd_rfork_thread.c @ 86:3973260705cc
nginx-0.0.1-2003-05-12-19:52:24 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 12 May 2003 15:52:24 +0000 |
parents | 3549c2bf9eaf |
children | 738fe44c70d5 |
comparison
equal
deleted
inserted
replaced
85:3549c2bf9eaf | 86:3973260705cc |
---|---|
9 extern int __isthreaded; | 9 extern int __isthreaded; |
10 | 10 |
11 | 11 |
12 typedef int ngx_tid_t; | 12 typedef int ngx_tid_t; |
13 | 13 |
14 #define NGX_MAX_THREADS 10 | |
15 | |
16 | 14 |
17 static inline int ngx_gettid(); | 15 static inline int ngx_gettid(); |
18 | 16 |
19 | 17 |
20 static char *stacks_start; | 18 static char *usrstack; |
21 static char *stacks_end; | |
22 static size_t stack_size; | |
23 static char *last_stack; | |
24 static int last_thread; | |
25 | |
26 static ngx_log_t *log; | |
27 | |
28 static ngx_tid_t tids[NGX_MAX_THREADS]; | |
29 | |
30 static int red_zone = 4096; | 19 static int red_zone = 4096; |
31 | 20 |
21 static size_t stack_size; | |
22 static size_t usable_stack_size; | |
23 static char *last_stack; | |
24 | |
25 static int threads; | |
26 static int nthreads; | |
27 static ngx_tid_t *tids; | |
32 | 28 |
33 /* the thread-safe errno */ | 29 /* the thread-safe errno */ |
34 | 30 |
35 static int errnos[NGX_MAX_THREADS]; | 31 static int errno0; /* the main thread's errno */ |
32 static int *errnos; | |
36 | 33 |
37 int *__error() | 34 int *__error() |
38 { | 35 { |
39 return &errnos[ngx_gettid()]; | 36 int tid; |
37 | |
38 tid = ngx_gettid(); | |
39 | |
40 return tid ? &errnos[tid - 1] : &errno0; | |
40 } | 41 } |
41 | 42 |
42 | 43 |
43 int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg) | 44 int ngx_create_thread(ngx_tid_t *tid, int (*func)(void *arg), void *arg, |
45 ngx_log_t *log) | |
44 { | 46 { |
45 int id, err; | 47 int id, err; |
46 char *stack_top; | 48 char *stack, *stack_top; |
47 | 49 |
48 last_stack += stack_size; | 50 if (threads >= nthreads) { |
49 stack_top = last_stack - red_zone; | 51 ngx_log_error(NGX_LOG_CRIT, log, 0, |
50 | 52 "no more than %d threads can be created", nthreads); |
51 if (stack_top > stacks_end) { | |
52 ngx_log_error(NGX_LOG_CRIT, log, 0, "no more threads allocated"); | |
53 return NGX_ERROR; | 53 return NGX_ERROR; |
54 } | 54 } |
55 | 55 |
56 #if 0 | 56 last_stack -= stack_size; |
57 stack = mmap(last_stack, usable_stack_size, PROT_READ|PROT_WRITE, | |
58 MAP_STACK, -1, 0); | |
59 if (stack == MAP_FAILED) { | |
60 ngx_log_error(NGX_LOG_ALERT, log, errno, | |
61 "mmap(%08X:%d, MAP_STACK) thread stack failed", | |
62 last_stack, usable_stack_size); | |
63 return NGX_ERROR; | |
64 } | |
65 | |
66 if (stack != last_stack) { | |
67 ngx_log_error(NGX_LOG_ALERT, log, 0, "stack address was changed"); | |
68 } | |
69 | |
70 stack_top = stack + usable_stack_size; | |
71 | |
72 printf("stack: %08X-%08X\n", stack, stack_top); | |
73 | |
74 #if 1 | |
75 id = rfork_thread(RFPROC|RFTHREAD|RFMEM, stack_top, func, arg); | |
76 #elif 1 | |
77 id = rfork_thread(RFPROC|RFMEM, stack_top, func, arg); | |
78 #elif 1 | |
79 id = rfork_thread(RFFDG|RFCFDG, stack_top, func, arg); | |
80 #else | |
57 id = rfork(RFFDG|RFCFDG); | 81 id = rfork(RFFDG|RFCFDG); |
58 #elif 0 | |
59 id = rfork_thread(RFFDG|RFCFDG, stack_top, func, arg); | |
60 #elif 0 | |
61 id = rfork_thread(RFPROC|RFMEM, stack_top, func, arg); | |
62 #else | |
63 id = rfork_thread(RFPROC|RFTHREAD|RFMEM, stack_top, func, arg); | |
64 #endif | 82 #endif |
83 | |
65 err = errno; | 84 err = errno; |
66 | 85 |
67 if (id == -1) { | 86 if (id == -1) { |
68 ngx_log_error(NGX_LOG_ALERT, log, err, "rfork() failed"); | 87 ngx_log_error(NGX_LOG_ALERT, log, err, "rfork() failed"); |
69 | 88 |
70 } else { | 89 } else { |
71 *tid = id; | 90 *tid = id; |
72 tids[last_thread++] = id; | 91 threads = (usrstack - stack_top) / stack_size; |
92 tids[threads] = id; | |
73 | 93 |
74 /* allow the spinlock in libc malloc() */ | 94 /* allow the spinlock in libc malloc() */ |
75 __isthreaded = 1; | 95 __isthreaded = 1; |
76 } | 96 } |
77 | 97 |
78 return err; | 98 return err; |
79 } | 99 } |
80 | 100 |
81 | 101 |
82 int ngx_init_thread_env(int n, size_t size, ngx_log_t *lg) | 102 int ngx_init_thread_env(int n, size_t size, ngx_log_t *log) |
83 { | 103 { |
84 int len, i; | 104 int len; |
85 char *usrstack, *zone; | 105 char *rz, *zone; |
86 | 106 |
87 log = lg; | 107 nthreads = n; |
88 | |
89 /* create the thread stacks */ | |
90 | 108 |
91 len = 4; | 109 len = 4; |
92 if (sysctlbyname("kern.usrstack", &usrstack, &len, NULL, 0) == -1) { | 110 if (sysctlbyname("kern.usrstack", &usrstack, &len, NULL, 0) == -1) { |
93 ngx_log_error(NGX_LOG_ALERT, log, errno, | 111 ngx_log_error(NGX_LOG_ALERT, log, errno, |
94 "sysctlbyname(kern.usrstack) failed"); | 112 "sysctlbyname(kern.usrstack) failed"); |
95 return NGX_ERROR; | 113 return NGX_ERROR; |
96 } | 114 } |
97 | 115 |
98 printf("usrstack: %08X\n", usrstack); | 116 printf("usrstack: %08X\n", usrstack); |
99 printf("red zone: %08X\n", usrstack - (size + red_zone)); | |
100 | 117 |
101 #if 1 | |
102 /* red zone */ | 118 /* red zone */ |
103 zone = mmap(usrstack - (size + red_zone), red_zone, | 119 rz = usrstack - (size + red_zone); |
104 PROT_NONE, MAP_ANON, -1, 0); | 120 |
121 printf("red zone: %08X\n", rz); | |
122 | |
123 zone = mmap(rz, red_zone, PROT_NONE, MAP_ANON, -1, 0); | |
105 if (zone == MAP_FAILED) { | 124 if (zone == MAP_FAILED) { |
106 ngx_log_error(NGX_LOG_ALERT, log, errno, | 125 ngx_log_error(NGX_LOG_ALERT, log, errno, |
107 "mmap(%d, PROT_NONE, MAP_ANON) failed", red_zone); | 126 "mmap(%08X:%d, PROT_NONE, MAP_ANON) red zone failed", |
127 rz, red_zone); | |
108 return NGX_ERROR; | 128 return NGX_ERROR; |
109 } | 129 } |
110 #else | 130 |
111 zone = usrstack - (size + red_zone); | 131 if (zone != rz) { |
112 #endif | 132 ngx_log_error(NGX_LOG_ALERT, log, 0, "red zone address was changed"); |
133 } | |
134 | |
135 /* create the thread errno array */ | |
136 ngx_test_null(errnos, ngx_calloc(n * sizeof(int), log), NGX_ERROR); | |
137 | |
138 /* create the thread tid array */ | |
139 ngx_test_null(tids, ngx_calloc((n + 1) * sizeof(ngx_tid_t), log), | |
140 NGX_ERROR); | |
141 | |
142 tids[0] = ngx_getpid(); | |
143 threads = 1; | |
113 | 144 |
114 last_stack = zone + red_zone; | 145 last_stack = zone + red_zone; |
115 | 146 usable_stack_size = size; |
116 for (i = 0; i < n; i++) { | |
117 last_stack -= size + red_zone; | |
118 printf("stack: %08X\n", last_stack); | |
119 last_stack = mmap(last_stack, size, PROT_READ|PROT_WRITE, | |
120 MAP_STACK, -1, 0); | |
121 if (last_stack == MAP_FAILED) { | |
122 ngx_log_error(NGX_LOG_ALERT, log, errno, | |
123 "mmap(%d, MAP_STACK) failed", size); | |
124 return NGX_ERROR; | |
125 } | |
126 } | |
127 | |
128 stacks_start = last_stack; | |
129 stack_size = size + red_zone; | 147 stack_size = size + red_zone; |
130 stacks_end = stacks_start + n * stack_size; | |
131 | |
132 tids[0] = ngx_getpid(); | |
133 last_thread = 1; | |
134 | 148 |
135 return NGX_OK; | 149 return NGX_OK; |
136 } | 150 } |
137 | 151 |
138 | 152 |
139 ngx_tid_t ngx_thread_self() | 153 ngx_tid_t ngx_thread_self() |
140 { | 154 { |
141 return tids[ngx_gettid()]; | 155 int tid; |
156 ngx_tid_t pid; | |
157 | |
158 tid = ngx_gettid(); | |
159 | |
160 if (tids[tid] == 0) { | |
161 pid = ngx_getpid(); | |
162 tids[tid] = pid; | |
163 return pid; | |
164 } | |
165 | |
166 return tids[tid]; | |
142 } | 167 } |
143 | 168 |
144 | 169 |
145 static inline int ngx_gettid() | 170 static inline int ngx_gettid() |
146 { | 171 { |
147 char *sp; | 172 char *sp; |
148 | 173 |
174 if (stack_size == 0) { | |
175 return 0; | |
176 } | |
177 | |
149 __asm__ ("mov %%esp, %0" : "=q" (sp)); | 178 __asm__ ("mov %%esp, %0" : "=q" (sp)); |
150 | 179 |
151 return (sp > stacks_end) ? 0 : ((sp - stacks_start) / stack_size + 1); | 180 return (usrstack - sp) / stack_size; |
152 } | 181 } |