mcache.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Per-P malloc cache for small objects.
  5. //
  6. // See malloc.h for an overview.
  7. #include "runtime.h"
  8. #include "arch.h"
  9. #include "malloc.h"
  10. extern volatile intgo runtime_MemProfileRate
  11. __asm__ (GOSYM_PREFIX "runtime.MemProfileRate");
  12. // dummy MSpan that contains no free objects.
  13. static MSpan emptymspan;
  14. MCache*
  15. runtime_allocmcache(void)
  16. {
  17. intgo rate;
  18. MCache *c;
  19. int32 i;
  20. runtime_lock(&runtime_mheap);
  21. c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc);
  22. runtime_unlock(&runtime_mheap);
  23. runtime_memclr((byte*)c, sizeof(*c));
  24. for(i = 0; i < NumSizeClasses; i++)
  25. c->alloc[i] = &emptymspan;
  26. // Set first allocation sample size.
  27. rate = runtime_MemProfileRate;
  28. if(rate > 0x3fffffff) // make 2*rate not overflow
  29. rate = 0x3fffffff;
  30. if(rate != 0)
  31. c->next_sample = runtime_fastrand1() % (2*rate);
  32. return c;
  33. }
  34. void
  35. runtime_freemcache(MCache *c)
  36. {
  37. runtime_MCache_ReleaseAll(c);
  38. runtime_lock(&runtime_mheap);
  39. runtime_purgecachedstats(c);
  40. runtime_FixAlloc_Free(&runtime_mheap.cachealloc, c);
  41. runtime_unlock(&runtime_mheap);
  42. }
  43. // Gets a span that has a free object in it and assigns it
  44. // to be the cached span for the given sizeclass. Returns this span.
  45. MSpan*
  46. runtime_MCache_Refill(MCache *c, int32 sizeclass)
  47. {
  48. MCacheList *l;
  49. MSpan *s;
  50. runtime_m()->locks++;
  51. // Return the current cached span to the central lists.
  52. s = c->alloc[sizeclass];
  53. if(s->freelist != nil)
  54. runtime_throw("refill on a nonempty span");
  55. if(s != &emptymspan)
  56. runtime_MCentral_UncacheSpan(&runtime_mheap.central[sizeclass], s);
  57. // Push any explicitly freed objects to the central lists.
  58. // Not required, but it seems like a good time to do it.
  59. l = &c->free[sizeclass];
  60. if(l->nlist > 0) {
  61. runtime_MCentral_FreeList(&runtime_mheap.central[sizeclass], l->list);
  62. l->list = nil;
  63. l->nlist = 0;
  64. }
  65. // Get a new cached span from the central lists.
  66. s = runtime_MCentral_CacheSpan(&runtime_mheap.central[sizeclass]);
  67. if(s == nil)
  68. runtime_throw("out of memory");
  69. if(s->freelist == nil) {
  70. runtime_printf("%d %d\n", s->ref, (int32)((s->npages << PageShift) / s->elemsize));
  71. runtime_throw("empty span");
  72. }
  73. c->alloc[sizeclass] = s;
  74. runtime_m()->locks--;
  75. return s;
  76. }
  77. void
  78. runtime_MCache_Free(MCache *c, MLink *p, int32 sizeclass, uintptr size)
  79. {
  80. MCacheList *l;
  81. // Put on free list.
  82. l = &c->free[sizeclass];
  83. p->next = l->list;
  84. l->list = p;
  85. l->nlist++;
  86. // We transfer a span at a time from MCentral to MCache,
  87. // so we'll do the same in the other direction.
  88. if(l->nlist >= (runtime_class_to_allocnpages[sizeclass]<<PageShift)/size) {
  89. runtime_MCentral_FreeList(&runtime_mheap.central[sizeclass], l->list);
  90. l->list = nil;
  91. l->nlist = 0;
  92. }
  93. }
  94. void
  95. runtime_MCache_ReleaseAll(MCache *c)
  96. {
  97. int32 i;
  98. MSpan *s;
  99. MCacheList *l;
  100. for(i=0; i<NumSizeClasses; i++) {
  101. s = c->alloc[i];
  102. if(s != &emptymspan) {
  103. runtime_MCentral_UncacheSpan(&runtime_mheap.central[i], s);
  104. c->alloc[i] = &emptymspan;
  105. }
  106. l = &c->free[i];
  107. if(l->nlist > 0) {
  108. runtime_MCentral_FreeList(&runtime_mheap.central[i], l->list);
  109. l->list = nil;
  110. l->nlist = 0;
  111. }
  112. }
  113. }