~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to lib/ts/ink_queue_ext.cc

  • Committer: Package Import Robot
  • Author(s): Aron Xu
  • Date: 2013-05-09 01:00:04 UTC
  • mto: (1.1.11) (5.3.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: package-import@ubuntu.com-20130509010004-9fqq9n0adseg3f8w
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 
 
3
  A brief file description
 
4
 
 
5
  @section license License
 
6
 
 
7
  Licensed to the Apache Software Foundation (ASF) under one
 
8
  or more contributor license agreements.  See the NOTICE file
 
9
  distributed with this work for additional information
 
10
  regarding copyright ownership.  The ASF licenses this file
 
11
  to you under the Apache License, Version 2.0 (the
 
12
  "License"); you may not use this file except in compliance
 
13
  with the License.  You may obtain a copy of the License at
 
14
 
 
15
      http://www.apache.org/licenses/LICENSE-2.0
 
16
 
 
17
  Unless required by applicable law or agreed to in writing, software
 
18
  distributed under the License is distributed on an "AS IS" BASIS,
 
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
20
  See the License for the specific language governing permissions and
 
21
  limitations under the License.
 
22
 */
 
23
 
 
24
/***********************************************************************
 
25
 
 
26
    Reclaimable freelist Implementation
 
27
 
 
28
***********************************************************************/
 
29
 
 
30
#include "ink_config.h"
 
31
#include <assert.h>
 
32
#include <memory.h>
 
33
#include <stdlib.h>
 
34
#include <unistd.h>
 
35
#include <sys/types.h>
 
36
#include <sys/mman.h>
 
37
#include "ink_atomic.h"
 
38
#include "ink_queue.h"
 
39
#include "ink_memory.h"
 
40
#include "ink_error.h"
 
41
#include "ink_assert.h"
 
42
#include "ink_resource.h"
 
43
#include "ink_queue_ext.h"
 
44
 
 
45
#if TS_USE_RECLAIMABLE_FREELIST
 
46
 
 
47
#define CEIL(x,y)   (((x) + (y) - 1L) / (y))
 
48
#define ROUND(x,l)  (((x) + ((l) - 1L)) & ~((l) - 1L))
 
49
 
 
50
#define MAX_NUM_FREELIST  1024
 
51
 
 
52
/*
 
53
 * Configurable Variables
 
54
 */
 
55
float cfg_reclaim_factor = 0.3;
 
56
int64_t cfg_max_overage = 10;
 
57
int64_t cfg_enable_reclaim = 0;
 
58
/*
 
59
 * Debug filter bit mask:
 
60
 *  bit 0: reclaim in ink_freelist_new
 
61
 *  bit 1: reclaim in ink_freelist_free
 
62
 *  bit 2: fetch memory from thread cache
 
63
 */
 
64
int64_t cfg_debug_filter;
 
65
 
 
66
static uint32_t page_size;
 
67
static uint32_t nr_freelist;
 
68
static uint64_t total_mem_in_byte;
 
69
static __thread InkThreadCache *ThreadCaches[MAX_NUM_FREELIST];
 
70
 
 
71
static inline pthread_t thread_id(void)
 
72
{
 
73
  static __thread pthread_t tid;
 
74
 
 
75
  return tid?tid:(tid = pthread_self());
 
76
}
 
77
#define THREAD_ID thread_id()
 
78
#define MAX_CHUNK_BYTE_SIZE (page_size << 8)
 
79
 
 
80
/*
 
81
 * For debug
 
82
 */
 
83
#if 1
 
84
#define show_info(tag, f, pCache) \
 
85
  __show_info(stdout, __FILE__, __LINE__, tag, f, pCache)
 
86
#else
 
87
#define show_info(tag, f, pCache) \
 
88
  __silent(__FILE__, __LINE__, tag, f, pCache)
 
89
#endif
 
90
#define error_info(tag, f, pCache) \
 
91
  __show_info(stderr, __FILE__, __LINE__, tag, f, pCache)
 
92
 
 
93
static inline void
 
94
__silent(const char *file, int line,
 
95
         const char *tag, InkFreeList *f, InkThreadCache *pCache) {}
 
96
 
 
97
static inline void
 
98
__show_info(FILE *fp, const char *file, int line,
 
99
            const char *tag, InkFreeList *f, InkThreadCache *pCache)
 
100
{
 
101
 
 
102
  fprintf(fp, "[%lx:%02u][%s:%05d][%s] %6.2fM t:%-8uf:%-4u m:%-4u avg:%-6.1f"
 
103
          " M:%-4u csbase:%-4u csize:%-4u tsize:%-6u cbsize:%u\n",
 
104
         (long)THREAD_ID, f->thread_cache_idx, file, line, tag,
 
105
         ((double)total_mem_in_byte/1024/1024),
 
106
         pCache->nr_total,
 
107
         pCache->nr_free,
 
108
         pCache->nr_min,
 
109
         pCache->nr_average,
 
110
         pCache->nr_malloc,
 
111
         f->chunk_size_base,
 
112
         f->chunk_size,
 
113
         f->type_size,
 
114
         f->chunk_byte_size);
 
115
}
 
116
 
 
117
static inline void
 
118
memory_alignment_init(InkFreeList *f, uint32_t type_size, uint32_t chunk_size,
 
119
                      uint32_t alignment)
 
120
{
 
121
  uint32_t chunk_byte_size, user_alignment;
 
122
 
 
123
  f->chunk_size_base = chunk_size;
 
124
  user_alignment = alignment;
 
125
  chunk_size = 1;
 
126
 
 
127
  /*
 
128
   * limit the size of each chunk and resize alignment.
 
129
   * 1) when size of chunk > MAX_CHUNK_BYTE_SIZE:
 
130
   *    alignment = page_size;
 
131
   * 2) when size of chunk <= MAX_CHUNK_BYTE_SIZE:
 
132
   *    alignment = (2^N * page_size),
 
133
   *    alignment should not larger than MAX_CHUNK_BYTE_SIZE
 
134
   */
 
135
  alignment = page_size;
 
136
  chunk_byte_size = ROUND(type_size + sizeof(InkChunkInfo), page_size);
 
137
  if (chunk_byte_size <= MAX_CHUNK_BYTE_SIZE) {
 
138
 
 
139
    chunk_byte_size = ROUND(type_size * f->chunk_size_base
 
140
                            + sizeof(InkChunkInfo), page_size);
 
141
 
 
142
    if (chunk_byte_size > MAX_CHUNK_BYTE_SIZE) {
 
143
      chunk_size = (MAX_CHUNK_BYTE_SIZE - sizeof(InkChunkInfo)) / type_size;
 
144
      chunk_byte_size = ROUND(type_size * chunk_size + sizeof(InkChunkInfo),
 
145
                              page_size);
 
146
    } else
 
147
      chunk_size = (chunk_byte_size - sizeof(InkChunkInfo)) / type_size;
 
148
 
 
149
    if (chunk_size > 1) {
 
150
      /* make alignment to be (2^N * page_size),
 
151
       * but not larger than MAX_CHUNK_BYTE_SIZE */
 
152
      while (alignment < chunk_byte_size)
 
153
        alignment <<= 1;
 
154
    }
 
155
  }
 
156
 
 
157
  if (user_alignment > alignment) {
 
158
    alignment = page_size;
 
159
    while (alignment < user_alignment)
 
160
      alignment <<= 1;
 
161
  }
 
162
  ink_release_assert(alignment <= MAX_CHUNK_BYTE_SIZE);
 
163
 
 
164
  f->alignment = alignment;
 
165
  f->type_size = type_size;
 
166
  f->chunk_size = chunk_size;
 
167
  f->chunk_addr_mask = ~((uintptr_t)(alignment - 1));
 
168
  f->chunk_byte_size = chunk_byte_size;
 
169
 
 
170
  return;
 
171
}
 
172
 
 
173
/*
 
174
 * mmap_align allocates _size_ bytes and returns a pointer to the
 
175
 * allocated memory, which address will be a multiple of _alignment_.
 
176
 *  1)the _size_ must be a multiple of page_size;
 
177
 *  2)the _alignment_ must be a power of page_size;
 
178
 */
 
179
static void*
 
180
mmap_align(size_t size, size_t alignment) {
 
181
  uintptr_t ptr;
 
182
  size_t adjust, extra = 0;
 
183
 
 
184
  ink_assert(size % page_size == 0);
 
185
 
 
186
  /* ask for extra memory if alignment > page_size */
 
187
  if (alignment > page_size) {
 
188
    extra = alignment - page_size;
 
189
  }
 
190
  void* result = mmap(NULL, size + extra,
 
191
                      PROT_READ|PROT_WRITE,
 
192
                      MAP_PRIVATE|MAP_ANONYMOUS,
 
193
                      -1, 0);
 
194
  if (result == MAP_FAILED) {
 
195
      xdump();
 
196
      ink_fatal(1, "Failed to mmap %zu bytes, %s", size, strerror(errno));
 
197
  }
 
198
 
 
199
  /* adjust the return memory so it is aligned */
 
200
  adjust = 0;
 
201
  ptr = (uintptr_t)result;
 
202
  if ((ptr & (alignment - 1)) != 0) {
 
203
    adjust = alignment - (ptr & (alignment - 1));
 
204
  }
 
205
 
 
206
  /* return the unused memory to the system */
 
207
  if (adjust > 0) {
 
208
    munmap((void*)ptr, adjust);
 
209
  }
 
210
  if (adjust < extra) {
 
211
    munmap((void*)(ptr + adjust + size), extra - adjust);
 
212
  }
 
213
 
 
214
  ptr += adjust;
 
215
  ink_assert((ptr & (alignment -1)) == 0);
 
216
  return (void*)ptr;
 
217
}
 
218
 
 
219
static inline InkChunkInfo *
 
220
get_chunk_info_addr(InkFreeList *f, void *item)
 
221
{
 
222
  uintptr_t chunk_addr;
 
223
 
 
224
  if (f->chunk_size > 1)
 
225
    chunk_addr = (uintptr_t)item & f->chunk_addr_mask;
 
226
  else
 
227
    chunk_addr = (uintptr_t)item;
 
228
 
 
229
  return (InkChunkInfo *)(chunk_addr + f->type_size * f->chunk_size);
 
230
}
 
231
 
 
232
static inline InkChunkInfo *
 
233
ink_chunk_create(InkFreeList *f, InkThreadCache *pCache)
 
234
{
 
235
  uint32_t i;
 
236
  uint32_t type_size, chunk_size;
 
237
  void *chunk_addr, *curr, *next;
 
238
  InkChunkInfo *pChunk;
 
239
 
 
240
  chunk_addr = mmap_align(f->chunk_byte_size, f->alignment);
 
241
  pChunk = (InkChunkInfo *)((char *)chunk_addr + f->type_size * f->chunk_size);
 
242
 
 
243
  type_size = f->type_size;
 
244
  chunk_size = f->chunk_size;
 
245
 
 
246
  pChunk->tid = THREAD_ID;
 
247
  pChunk->head = chunk_addr;
 
248
  pChunk->type_size = type_size;
 
249
  pChunk->chunk_size = chunk_size;
 
250
  pChunk->length = f->chunk_byte_size;
 
251
  pChunk->allocated = 0;
 
252
  pChunk->pThreadCache = pCache;
 
253
  pChunk->link = Link<InkChunkInfo>();
 
254
 
 
255
  curr = pChunk->head;
 
256
  pChunk->inner_free_list = curr;
 
257
  for (i = 1; i < chunk_size; i++) {
 
258
    next = (void *)((char *)curr + type_size);
 
259
    *(void **)curr = next;
 
260
    curr = next;
 
261
  }
 
262
  *(void **)curr = NULL;
 
263
 
 
264
  ink_atomic_increment(&f->count, chunk_size);
 
265
  ink_atomic_increment(&total_mem_in_byte, f->chunk_byte_size);
 
266
 
 
267
  pCache->free_chunk_list.push(pChunk);
 
268
  pCache->nr_free_chunks++;
 
269
  return pChunk;
 
270
}
 
271
 
 
272
static inline void
 
273
ink_chunk_delete(InkFreeList *f, InkThreadCache *pCache, InkChunkInfo *pChunk)
 
274
{
 
275
  void *chunk_addr = pChunk->head;
 
276
 
 
277
  ink_assert(pChunk->allocated == 0);
 
278
 
 
279
  pCache->free_chunk_list.remove(pChunk);
 
280
  pCache->nr_free_chunks--;
 
281
 
 
282
  if (unlikely(munmap(chunk_addr, f->chunk_byte_size))) {
 
283
      xdump();
 
284
      ink_fatal(1, "Failed to munmap %u bytes, %s", f->chunk_byte_size,
 
285
                strerror(errno));
 
286
  }
 
287
 
 
288
  ink_atomic_increment((int *)&f->count, -f->chunk_size);
 
289
 
 
290
  /*
 
291
   * TODO: I had used ink_atomic_increment() here, but it would
 
292
   * lead to incorrect value in linux OS, I don't know why:
 
293
   *  ink_atomic_decrement((int64_t *)&total_mem_in_byte, -f->chunk_byte_size);
 
294
   *
 
295
   * So I create a new wrap, ink_atomic_decrement(), in ink_atomic.h,
 
296
   * it works well. But we should create the same wrap for other OS.
 
297
   */
 
298
  ink_atomic_decrement(&total_mem_in_byte, f->chunk_byte_size);
 
299
}
 
300
 
 
301
static inline void *
 
302
malloc_whole_chunk(InkFreeList *f, InkThreadCache *pCache, InkChunkInfo *pChunk)
 
303
{
 
304
  uint32_t i;
 
305
  uint32_t type_size, chunk_size;
 
306
  void *next, *item;
 
307
 
 
308
  ink_assert(pChunk->allocated == 0);
 
309
 
 
310
  type_size = f->type_size;
 
311
  chunk_size = f->chunk_size;
 
312
 
 
313
  item = pChunk->head;
 
314
  for (i = 1; i < chunk_size; i++) {
 
315
    next = (void *)((char *)item + i * type_size);
 
316
    ink_atomic_increment(&pCache->nr_free, 1);
 
317
    ink_atomiclist_push(&pCache->outer_free_list, next);
 
318
  }
 
319
 
 
320
  pChunk->allocated += chunk_size;
 
321
  pChunk->inner_free_list = NULL;
 
322
  pCache->nr_total += chunk_size;
 
323
 
 
324
  ink_atomic_increment(&f->allocated, chunk_size);
 
325
 
 
326
  return item;
 
327
}
 
328
 
 
329
static inline void *
 
330
malloc_from_chunk(InkFreeList *f, InkThreadCache *pCache, InkChunkInfo *pChunk)
 
331
{
 
332
  void *item;
 
333
 
 
334
  if ((item = pChunk->inner_free_list)) {
 
335
    pChunk->inner_free_list  = *(void **)item;
 
336
    pChunk->allocated++;
 
337
    pCache->nr_total++;
 
338
    ink_atomic_increment(&f->allocated, 1);
 
339
  }
 
340
 
 
341
  return item;
 
342
}
 
343
 
 
344
static inline void
 
345
free_to_chunk(InkFreeList *f, InkThreadCache *pCache, void *item)
 
346
{
 
347
  InkChunkInfo *pChunk;
 
348
 
 
349
  pChunk = get_chunk_info_addr(f, item);
 
350
  pChunk->allocated--;
 
351
  ink_atomic_increment((int *)&f->allocated, -1);
 
352
  pCache->nr_total--;
 
353
 
 
354
  *(void **)item = pChunk->inner_free_list;
 
355
  pChunk->inner_free_list = item;
 
356
 
 
357
  if (pChunk->allocated == 0)
 
358
    ink_chunk_delete(f, pCache, pChunk);
 
359
}
 
360
 
 
361
static inline void *
 
362
malloc_from_cache(InkFreeList *f, InkThreadCache *pCache, uint32_t nr)
 
363
{
 
364
  void *item;
 
365
  InkChunkInfo *pChunk;
 
366
 
 
367
  pChunk = pCache->free_chunk_list.head;
 
368
  while (pChunk) {
 
369
    while ((item = malloc_from_chunk(f, pCache, pChunk))) {
 
370
      if (--nr == 0)
 
371
        return item;
 
372
 
 
373
      ink_atomic_increment(&pCache->nr_free, 1);
 
374
      ink_atomiclist_push(&pCache->outer_free_list, item);
 
375
    }
 
376
    pChunk = pChunk->link.next;
 
377
  }
 
378
 
 
379
  pChunk = ink_chunk_create(f, pCache);
 
380
  if (nr == f->chunk_size)
 
381
    return malloc_whole_chunk(f, pCache, pChunk);
 
382
 
 
383
  while ((item = malloc_from_chunk(f, pCache, pChunk))) {
 
384
    if (--nr == 0)
 
385
      return item;
 
386
 
 
387
    ink_atomic_increment(&pCache->nr_free, 1);
 
388
    ink_atomiclist_push(&pCache->outer_free_list, item);
 
389
  }
 
390
 
 
391
  ink_assert(0);
 
392
  return NULL;
 
393
}
 
394
 
 
395
static inline void
 
396
free_to_cache(InkFreeList *f, InkThreadCache *pCache, void *item, uint32_t nr)
 
397
{
 
398
  uint32_t n = nr;
 
399
 
 
400
  if (item)
 
401
    free_to_chunk(f, pCache, item);
 
402
 
 
403
  while (n && (item = ink_atomiclist_pop(&pCache->outer_free_list))) {
 
404
    free_to_chunk(f, pCache, item);
 
405
    n--;
 
406
  }
 
407
  ink_atomic_increment((int *)&pCache->nr_free, -(nr - n));
 
408
}
 
409
 
 
410
static inline void
 
411
refresh_average_info(InkThreadCache *pCache)
 
412
{
 
413
  uint32_t nr_free;
 
414
  float nr_average;
 
415
 
 
416
  nr_free = pCache->nr_free;
 
417
  nr_average = pCache->nr_average;
 
418
 
 
419
  if (pCache->status == 1 || nr_free < pCache->nr_min)
 
420
    pCache->nr_min = nr_free;
 
421
 
 
422
  pCache->nr_average = (nr_average * (1 - cfg_reclaim_factor)) +
 
423
                       (nr_free * cfg_reclaim_factor);
 
424
}
 
425
 
 
426
static inline bool
 
427
need_to_reclaim(InkFreeList *f, InkThreadCache *pCache, pthread_t tid)
 
428
{
 
429
  if (!cfg_enable_reclaim)
 
430
    return false;
 
431
 
 
432
  if(pCache->nr_free >= pCache->nr_average &&
 
433
     pCache->nr_total > f->chunk_size_base) {
 
434
    if (pCache->nr_overage++ >= cfg_max_overage) {
 
435
      pCache->nr_overage = 0;
 
436
      return true;
 
437
    }
 
438
    return false;
 
439
  }
 
440
 
 
441
  pCache->nr_overage = 0;
 
442
  return false;
 
443
}
 
444
 
 
445
void
 
446
reclaimable_freelist_init(InkFreeList **fl, const char *name,
 
447
                          uint32_t type_size, uint32_t chunk_size,
 
448
                          uint32_t alignment)
 
449
{
 
450
  InkFreeList *f;
 
451
  ink_freelist_list *fll = freelists;
 
452
 
 
453
  /* quick test for power of 2 */
 
454
  ink_assert(!(alignment & (alignment - 1)));
 
455
 
 
456
  if (!page_size)
 
457
    page_size = sysconf(_SC_PAGESIZE);
 
458
 
 
459
  /* NOTE: it's safe to operate on this global list because
 
460
   * ink_freelist_init() is only called from single-threaded
 
461
   * initialization code. */
 
462
  while (fll) {
 
463
    /* Reuse InkFreeList if it has the same aligned type_size. */
 
464
    if (fll->fl->type_size == type_size) {
 
465
      fll->fl->refcnt++;
 
466
      *fl = fll->fl;
 
467
      return;
 
468
    }
 
469
    fll = fll->next;
 
470
  }
 
471
 
 
472
  f = (InkFreeList *)ats_memalign(alignment, sizeof(InkFreeList));
 
473
  fll = (ink_freelist_list *)ats_memalign(alignment, sizeof(ink_freelist_list));
 
474
  fll->fl = f;
 
475
  fll->next = freelists;
 
476
  freelists = fll;
 
477
 
 
478
  f->name = name;
 
479
  f->count = 0;
 
480
  f->allocated = 0;
 
481
  f->allocated_base = 0;
 
482
  f->count_base = 0;
 
483
 
 
484
  memory_alignment_init(f, type_size, chunk_size, alignment);
 
485
 
 
486
  f->refcnt = 1;
 
487
  f->pThreadCache = NULL;
 
488
  f->nr_thread_cache = 0;
 
489
  f->thread_cache_idx = nr_freelist++;
 
490
  ink_assert(f->thread_cache_idx < MAX_NUM_FREELIST);
 
491
  ink_mutex_init(&f->lock, "InkFreeList Lock");
 
492
 
 
493
  *fl = f;
 
494
}
 
495
 
 
496
void *
 
497
reclaimable_freelist_new(InkFreeList *f)
 
498
{
 
499
  void *ptr;
 
500
  uint32_t i, nr;
 
501
  uint32_t old_value;
 
502
  uint32_t num_to_move;
 
503
  InkChunkInfo *pChunk = NULL;
 
504
  InkThreadCache *pCache, *pNextCache;
 
505
 
 
506
  /* no thread cache, create it */
 
507
  if (unlikely((pCache = ThreadCaches[f->thread_cache_idx]) == NULL)) {
 
508
    pCache = (InkThreadCache *) ats_calloc(1, sizeof(InkThreadCache));
 
509
 
 
510
    pCache->f = f;
 
511
    pCache->free_chunk_list = DLL<InkChunkInfo>();
 
512
 
 
513
    /* this lock will only be accessed when initializing
 
514
     * thread cache, so it won't damage performance */
 
515
    ink_mutex_acquire(&f->lock);
 
516
    ink_atomiclist_init(&pCache->outer_free_list, f->name, 0);
 
517
 
 
518
    nr = CEIL(f->chunk_size_base, f->chunk_size);
 
519
    for (i = 0; i < nr; i++) {
 
520
      pChunk = ink_chunk_create(f, pCache);
 
521
    }
 
522
 
 
523
    pCache->nr_malloc = 1;
 
524
 
 
525
    ThreadCaches[f->thread_cache_idx] = pCache;
 
526
 
 
527
    if (f->pThreadCache) {
 
528
      /* we will loop pCache.next without lock, following
 
529
       * statement's sequence is important for us. */
 
530
      pCache->next = f->pThreadCache;
 
531
      pCache->prev = f->pThreadCache->prev;
 
532
      pCache->next->prev = pCache;
 
533
      pCache->prev->next = pCache;
 
534
    } else {
 
535
      pCache->next = pCache;
 
536
      pCache->prev = pCache;
 
537
    }
 
538
 
 
539
    f->pThreadCache = pCache;
 
540
    f->nr_thread_cache++;
 
541
 
 
542
    ink_mutex_release(&f->lock);
 
543
 
 
544
    ptr = malloc_whole_chunk(f, pCache, pChunk);
 
545
    return ptr;
 
546
  }
 
547
 
 
548
  pCache->status = 0;
 
549
 
 
550
  /* priority to fetch memory from outer_free_list */
 
551
  if ((ptr = ink_atomiclist_pop(&pCache->outer_free_list))) {
 
552
    old_value = ink_atomic_increment((int *)&pCache->nr_free, -1);
 
553
    ink_release_assert(old_value > 0);
 
554
    ink_atomic_increment(&pCache->nr_malloc, 1);
 
555
    return ptr;
 
556
  }
 
557
 
 
558
  /* try to steal memory from other thread's outer_free_list */
 
559
  pNextCache = pCache->next;
 
560
  while (pNextCache != pCache) {
 
561
    if ((ptr = ink_atomiclist_pop(&pNextCache->outer_free_list))) {
 
562
          old_value = ink_atomic_increment((int *)&pNextCache->nr_free, -1);
 
563
          ink_release_assert(old_value > 0);
 
564
          ink_atomic_increment(&pNextCache->nr_malloc, 1);
 
565
          return ptr;
 
566
    }
 
567
    pNextCache = pNextCache->next;
 
568
  }
 
569
 
 
570
  /* try to reclaim memory from all caches in the same thread */
 
571
  for (i = 0; i < nr_freelist; i++) {
 
572
    if ((pNextCache = ThreadCaches[i]) == NULL)
 
573
      continue;
 
574
 
 
575
    if (need_to_reclaim(pNextCache->f, pNextCache, THREAD_ID)) {
 
576
      if (cfg_debug_filter & 0x1)
 
577
        show_info("F", pNextCache->f, pNextCache);
 
578
 
 
579
      num_to_move = MIN(pNextCache->nr_average, pNextCache->nr_free);
 
580
 
 
581
      free_to_cache(pNextCache->f, pNextCache, NULL, num_to_move);
 
582
 
 
583
      if (cfg_debug_filter & 0x1)
 
584
        show_info("-", pNextCache->f, pNextCache);
 
585
 
 
586
      refresh_average_info(pNextCache);
 
587
    }
 
588
  }
 
589
 
 
590
  /* finally, fetch from thread local cache */
 
591
  if (cfg_debug_filter & 0x2)
 
592
    show_info("M", f, pCache);
 
593
  ptr = malloc_from_cache(f, pCache, f->chunk_size);
 
594
  if (cfg_debug_filter & 0x2)
 
595
    show_info("+", f, pCache);
 
596
 
 
597
  refresh_average_info(pCache);
 
598
  ink_atomic_increment(&pCache->nr_malloc, 1);
 
599
  return ptr;
 
600
}
 
601
 
 
602
void
 
603
reclaimable_freelist_free(InkFreeList *f, void *item)
 
604
{
 
605
  InkChunkInfo *pChunk;
 
606
  InkThreadCache *pCache;
 
607
 
 
608
  if (item == NULL)
 
609
    return;
 
610
 
 
611
  pChunk = get_chunk_info_addr(f, item);
 
612
  pCache = pChunk->pThreadCache;
 
613
 
 
614
  ink_atomic_increment((int *)&pCache->nr_malloc, -1);
 
615
  if (ink_atomic_cas((int *)&pCache->status, 0, 1))
 
616
    refresh_average_info(pCache);
 
617
 
 
618
  ink_atomic_increment(&pCache->nr_free, 1);
 
619
  ink_atomiclist_push(&pCache->outer_free_list, item);
 
620
}
 
621
#endif