1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 #include "systhr.h"
54 #include "pool_pvt.h"
55
56
57
58
59 #include "util.h"
60
61
62
63
64
65
66 #include <stdlib.h>
67 #include <string.h>
68
69
70
71
72
73
74
75 static pool_config_t pool_config =
POOL_CONFIG_INIT;
76
77
78 static pool_global_stats_t pool_global_stats;
79
80 static int
81 pool_internal_init()
82 {
83
84
85
86
87 if (pool_config.block_size ==
0) {
88
89 }
90
91 return 0;
92 }
93
94 NSAPI_PUBLIC int
95 pool_init(pblock *pb, Session *sn, Request *rq)
96 {
97
98
99 char *str_block_size =
"16384";
100 char *str_pool_disable =
"false";
101 int n;
102
103
104
105 if (str_block_size !=
NULL) {
106 n = atoi(str_block_size);
107 if (n >
0)
108 pool_config.block_size = n;
109 }
110
111 if (str_pool_disable && util_getboolean(str_pool_disable,
PR_TRUE)) {
112
113 pool_config.block_size =
0;
114 pool_config.retain_size =
0;
115 pool_config.retain_num =
0;
116 }
117
118 pool_internal_init();
119
120 return REQ_PROCEED;
121 }
122
123 static block_t *
124 _create_block(
pool_t *pool,
int size)
125 {
126 block_t *newblock;
127 char *newdata;
128 block_t **blk_ptr;
129 long blen;
130
131
132 for (blk_ptr = &pool->free_blocks;
133 (newblock = *blk_ptr) !=
NULL; blk_ptr = &newblock->next) {
134
135
136 blen = newblock->end - newblock->data;
137 if (blen >= size) {
138
139
140 *blk_ptr = newblock->next;
141 pool->free_size -= blen;
142 --pool->free_num;
143
144
145 newblock->start = newblock->data;
146 goto done;
147 }
148 }
149
150 newblock = (
block_t *)
PERM_MALLOC(
sizeof(
block_t));
151 newdata = (
char *)
PERM_MALLOC(size);
152 if (newblock ==
NULL || (newdata ==
NULL && size !=
0)) {
153
154
155 PERM_FREE(newblock);
156 PERM_FREE(newdata);
157
158 return NULL;
159 }
160 newblock->data = newdata;
161 newblock->start = newblock->data;
162 newblock->end = newblock->data + size;
163 newblock->next =
NULL;
164 blen = size;
165
166 #ifdef POOL_GLOBAL_STATISTICS
167 PR_AtomicIncrement((PRInt32 *)&pool_global_stats.blkAlloc);
168 #endif
169
170 done:
171
172 #ifdef PER_POOL_STATISTICS
173 ++pool->stats.blkAlloc;
174 #endif
175
176 return newblock;
177 }
178
179 static void
180 _free_block(
block_t *block)
181 {
182 #ifdef POOL_ZERO_DEBUG
183 long blen = block->end - block->data;
184 memset(block->data,
POOL_ZERO_DEBUG, blen);
185 #endif
186
187 PERM_FREE(block->data);
188
189 #ifdef POOL_ZERO_DEBUG
190 memset(block,
POOL_ZERO_DEBUG,
sizeof(block));
191 #endif
192
193 PERM_FREE(block);
194
195 #ifdef POOL_GLOBAL_STATISTICS
196 PR_AtomicIncrement((PRInt32 *)&pool_global_stats.blkFree);
197 #endif
198 }
199
200
201
202
203
204
205 block_t *
206 _ptr_in_pool(
pool_t *pool,
const void *ptr)
207 {
208 block_t *block_ptr =
NULL;
209
210
211
212 if (
POOL_PTR_IN_BLOCK(pool->curr_block, ptr)) {
213 block_ptr = pool->curr_block;
214 }
215 else {
216 for (block_ptr = pool->used_blocks; block_ptr; block_ptr = block_ptr->next) {
217 if (
POOL_PTR_IN_BLOCK(block_ptr, ptr))
218 break;
219 }
220 }
221 return block_ptr;
222 }
223
224
225 NSAPI_PUBLIC pool_handle_t *
226 pool_create()
227 {
228 pool_t *newpool;
229
230 newpool = (
pool_t *)
PERM_MALLOC(
sizeof(
pool_t));
231
232 if (newpool) {
233
234
235
236
237
238
239
240 newpool->used_blocks =
NULL;
241 newpool->free_blocks =
NULL;
242 newpool->free_size =
0;
243 newpool->free_num =
0;
244 newpool->size =
0;
245 newpool->next =
NULL;
246
247 #ifdef PER_POOL_STATISTICS
248
249 memset((
void *)(&newpool->stats),
0,
sizeof(newpool->stats));
250 newpool->stats.thread = PR_GetCurrentThread();
251 newpool->stats.created = PR_Now();
252 #endif
253
254
255 newpool->curr_block =_create_block(newpool, pool_config.block_size);
256 if (newpool->curr_block ==
NULL) {
257
258 pool_destroy((
pool_handle_t *)newpool);
259
260 return NULL;
261 }
262
263
264
265
266
267
268
269
270
271
272 #ifdef PER_POOL_STATISTICS
273 newpool->stats.poolId = pool_global_stats.createCnt;
274 #endif
275
276
277 }
278 else {
279
280
281 }
282
283 return (
pool_handle_t *)newpool;
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 NSAPI_PUBLIC void *
302 pool_mark(
pool_handle_t *pool_handle)
303 {
304 pool_t *pool = (
pool_t *)pool_handle;
305
306
307
308 if (pool ==
NULL)
309 return NULL;
310
311 #ifdef PER_POOL_STATISTICS
312 pool->stats.thread = PR_GetCurrentThread();
313 #endif
314
315
316 if (pool->curr_block->start == pool->curr_block->end)
317 return pool->curr_block;
318
319 return (
void *)(pool->curr_block->start);
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336 NSAPI_PUBLIC void
337 pool_recycle(
pool_handle_t *pool_handle,
void *mark)
338 {
339 pool_t *pool = (
pool_t *)pool_handle;
340 block_t *tmp_blk;
341 unsigned long blen;
342
343
344
345 if (pool ==
NULL)
346 return;
347
348
349 tmp_blk = pool->curr_block;
350
351
352
353 for (;;) {
354
355
356 if (tmp_blk == mark) {
357 pool->curr_block = tmp_blk;
358 break;
359 }
360
361
362 if (
POOL_PTR_IN_BLOCK(tmp_blk, mark)) {
363
364
365 if (tmp_blk == pool->curr_block) {
366 blen = tmp_blk->start - (
char *)mark;
367 }
else {
368 blen = tmp_blk->end - (
char *)mark;
369 }
370 pool->size -= blen;
371
372 tmp_blk->start = (
char *)mark;
373 pool->curr_block = tmp_blk;
374 break;
375 }
376
377
378 if (tmp_blk == pool->curr_block) {
379
380 blen = tmp_blk->start - tmp_blk->data;
381 }
382 else {
383
384 blen = tmp_blk->end - tmp_blk->data;
385 }
386 tmp_blk->start = tmp_blk->data;
387 pool->size -= blen;
388
389
390
391
392
393
394 if (pool->used_blocks ==
NULL) {
395
396 pool->curr_block = tmp_blk;
397 break;
398 }
399
400
401
402
403 if ((pool->free_size + blen) <= pool_config.retain_size &&
404 pool->free_num < pool_config.retain_num) {
405
406
407
408
409
410
411
412
413 tmp_blk->next = pool->free_blocks;
414 pool->free_blocks = tmp_blk;
415 pool->free_size += blen;
416 ++pool->free_num;
417 }
418 else {
419
420 _free_block(tmp_blk);
421 }
422
423 #ifdef PER_POOL_STATISTICS
424
425 #endif
426
427
428 tmp_blk = pool->used_blocks;
429 pool->used_blocks = tmp_blk->next;
430 }
431 }
432
433 NSAPI_PUBLIC void
434 pool_destroy(
pool_handle_t *pool_handle)
435 {
436 pool_t *pool = (
pool_t *)pool_handle;
437 block_t *tmp_blk;
438
439
440
441 if (pool ==
NULL)
442 return;
443
444 if (pool->curr_block)
445 _free_block(pool->curr_block);
446
447 while(pool->used_blocks) {
448 tmp_blk = pool->used_blocks;
449 pool->used_blocks = tmp_blk->next;
450 _free_block(tmp_blk);
451 }
452
453 while(pool->free_blocks) {
454 tmp_blk = pool->free_blocks;
455 pool->free_blocks = tmp_blk->next;
456 _free_block(tmp_blk);
457 }
458
459 {
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476 }
477
478 #ifdef POOL_ZERO_DEBUG
479 memset(pool,
POOL_ZERO_DEBUG,
sizeof(pool));
480 #endif
481
482 PERM_FREE(pool);
483
484 return;
485 }
486
487
488 NSAPI_PUBLIC void *
489 pool_malloc(
pool_handle_t *pool_handle,
size_t size)
490 {
491 pool_t *pool = (
pool_t *)pool_handle;
492 block_t *curr_block;
493 long reqsize, blocksize;
494 char *ptr;
495
496 if (pool ==
NULL)
497 return PERM_MALLOC(size);
498
499 reqsize =
ALIGN(size);
500 if (reqsize ==
0) {
501
502 reqsize =
WORD_SIZE;
503 }
504
505 curr_block = pool->curr_block;
506 ptr = curr_block->start;
507 curr_block->start += reqsize;
508
509
510 if (curr_block->start > curr_block->end) {
511
512
513
514 curr_block->start -= reqsize;
515
516
517 pool->size += curr_block->end - curr_block->start;
518
519 #ifdef PER_POOL_STATISTICS
520 if (pool->size > pool->stats.maxAlloc) {
521 pool->stats.maxAlloc = pool->size;
522 }
523 #endif
524
525
526 curr_block->next = pool->used_blocks;
527 pool->used_blocks = curr_block;
528
529
530 blocksize = reqsize;
531 if (blocksize < pool_config.block_size)
532 blocksize = pool_config.block_size;
533
534 curr_block = _create_block(pool, blocksize);
535 pool->curr_block = curr_block;
536
537 if (curr_block ==
NULL) {
538
539
540
541 return NULL;
542 }
543
544 ptr = curr_block->start;
545 curr_block->start += reqsize;
546 }
547
548 pool->size += reqsize;
549
550
551 #ifdef PER_POOL_STATISTICS
552 if (pool->size > pool->stats.maxAlloc) {
553 pool->stats.maxAlloc = pool->size;
554 }
555 ++pool->stats.allocCnt;
556 pool->stats.thread = PR_GetCurrentThread();
557 #endif
558
559 return ptr;
560 }
561
562 NSAPI_PUBLIC void
563 pool_free(
pool_handle_t *pool_handle,
void *ptr)
564 {
565 pool_t *pool = (
pool_t *)pool_handle;
566
567 if (ptr ==
NULL)
568 return;
569
570 if (pool ==
NULL) {
571 PERM_FREE(ptr);
572 return;
573 }
574
575
576
577 #ifdef PER_POOL_STATISTICS
578
579 ++pool->stats.freeCnt;
580 pool->stats.thread = PR_GetCurrentThread();
581
582 #endif
583
584 return;
585 }
586
587 NSAPI_PUBLIC void *
588 pool_calloc(
pool_handle_t *pool_handle,
size_t nelem,
size_t elsize)
589 {
590 void *ptr;
591
592 if (pool_handle ==
NULL)
593 return calloc(
1, elsize * nelem);
594
595 ptr = pool_malloc(pool_handle, elsize * nelem);
596 if (ptr)
597 memset(ptr,
0, elsize * nelem);
598 return ptr;
599 }
600
601 NSAPI_PUBLIC void *
602 pool_realloc(
pool_handle_t *pool_handle,
void *ptr,
size_t size)
603 {
604 pool_t *pool = (
pool_t *)pool_handle;
605 void *newptr;
606 block_t *block_ptr;
607 size_t oldsize;
608
609 if (pool ==
NULL)
610 return PERM_REALLOC(ptr, size);
611
612 if ( (newptr = pool_malloc(pool_handle, size)) ==
NULL)
613 return NULL;
614
615
616
617
618
619
620
621 if ( !(block_ptr = _ptr_in_pool(pool, ptr)) ) {
622
623 return newptr;
624 }
625
626 oldsize = block_ptr->end - (
char *)ptr ;
627 if (oldsize > size)
628 oldsize = size;
629 memmove((
char *)newptr, (
char *)ptr, oldsize);
630
631 return newptr;
632 }
633
634 NSAPI_PUBLIC char *
635 pool_strdup(
pool_handle_t *pool_handle,
const char *orig_str)
636 {
637 char *new_str;
638 int len = strlen(orig_str);
639
640 if (pool_handle ==
NULL)
641 return PERM_STRDUP(orig_str);
642
643 new_str = (
char *)pool_malloc(pool_handle, len+
1);
644
645 if (new_str)
646 memcpy(new_str, orig_str, len+
1);
647
648 return new_str;
649 }
650
651 NSAPI_PUBLIC long
652 pool_space(
pool_handle_t *pool_handle)
653 {
654 pool_t *pool = (
pool_t *)pool_handle;
655
656 return pool->size;
657 }
658
659 NSAPI_PUBLIC int pool_enabled()
660 {
661 if (getThreadMallocKey() == -
1)
662 return 0;
663
664 if (!systhread_getdata(getThreadMallocKey()))
665 return 0;
666
667 return 1;
668 }
669
670 #ifdef DEBUG
671 NSAPI_PUBLIC void INTpool_assert(
pool_handle_t *pool_handle,
const void *ptr)
672 {
673 pool_t *pool = (
pool_t *)pool_handle;
674
675 if (pool ==
NULL)
676 return;
677
678
679 }
680 #endif
681
682 NSAPI_PUBLIC pool_config_t *pool_getConfig(
void)
683 {
684 return &pool_config;
685 }
686
687 #ifdef POOL_GLOBAL_STATISTICS
688 NSAPI_PUBLIC pool_global_stats_t *pool_getGlobalStats(
void)
689 {
690 return &pool_global_stats;
691 }
692 #endif
693
694 #ifdef PER_POOL_STATISTICS
695 NSAPI_PUBLIC pool_stats_t *pool_getPoolStats(
pool_handle_t *pool_handle)
696 {
697 pool_t *pool = (
pool_t *)pool_handle;
698
699 if (pool ==
NULL)
700 return NULL;
701
702 return &pool->stats;
703 }
704 #endif
705
706
707 sstr_t sstrdup_pool(
pool_handle_t *pool,
sstr_t s) {
708 sstr_t newstring;
709 newstring.ptr = (
char*)pool_malloc(pool, s.length +
1);
710 if (newstring.ptr !=
NULL) {
711 newstring.length = s.length;
712 newstring.ptr[newstring.length] =
0;
713
714 memcpy(newstring.ptr, s.ptr, s.length);
715 }
716
717 return newstring;
718 }
719
720