LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // See malloc.h for overview. | 5 // See malloc.h for overview. |
6 // | 6 // |
7 // TODO(rsc): double-check stats. | 7 // TODO(rsc): double-check stats. |
8 | 8 |
9 package runtime | 9 package runtime |
10 #include "runtime.h" | 10 #include "runtime.h" |
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 if(false) { | 741 if(false) { |
742 runtime·printf("new %S: %p\n", *typ->string, ret
); | 742 runtime·printf("new %S: %p\n", *typ->string, ret
); |
743 } | 743 } |
744 runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObjec
t); | 744 runtime·settype(ret, (uintptr)typ | TypeInfo_SingleObjec
t); |
745 } | 745 } |
746 } | 746 } |
747 | 747 |
748 return ret; | 748 return ret; |
749 } | 749 } |
750 | 750 |
751 static uint64 stackcache; // Lock-free stack of StackCacheNode. | |
752 | |
753 typedef struct StackCacheNode StackCacheNode; | 751 typedef struct StackCacheNode StackCacheNode; |
754 struct StackCacheNode | 752 struct StackCacheNode |
755 { | 753 { |
756 » LFNode; | 754 » StackCacheNode *next; |
757 void* batch[StackCacheBatch-1]; | 755 void* batch[StackCacheBatch-1]; |
758 }; | 756 }; |
| 757 |
| 758 static StackCacheNode *stackcache; |
| 759 static Lock stackcachemu; |
759 | 760 |
760 // stackcacherefill/stackcacherelease implement global cache of stack segments. | 761 // stackcacherefill/stackcacherelease implement global cache of stack segments. |
761 // The cache is required to prevent unlimited growth of per-thread caches. | 762 // The cache is required to prevent unlimited growth of per-thread caches. |
762 static void | 763 static void |
763 stackcacherefill(void) | 764 stackcacherefill(void) |
764 { | 765 { |
765 StackCacheNode *n; | 766 StackCacheNode *n; |
766 int32 i, pos; | 767 int32 i, pos; |
767 | 768 |
768 » n = (StackCacheNode*)runtime·lfstackpop(&stackcache); | 769 » runtime·lock(&stackcachemu); |
| 770 » n = stackcache; |
| 771 » if(n) |
| 772 » » stackcache = n->next; |
| 773 » runtime·unlock(&stackcachemu); |
769 if(n == nil) { | 774 if(n == nil) { |
770 n = (StackCacheNode*)runtime·SysAlloc(FixedStack*StackCacheBatch
); | 775 n = (StackCacheNode*)runtime·SysAlloc(FixedStack*StackCacheBatch
); |
771 if(n == nil) | 776 if(n == nil) |
772 runtime·throw("out of memory (staccachekrefill)"); | 777 runtime·throw("out of memory (staccachekrefill)"); |
773 runtime·xadd64(&mstats.stacks_sys, FixedStack*StackCacheBatch); | 778 runtime·xadd64(&mstats.stacks_sys, FixedStack*StackCacheBatch); |
774 for(i = 0; i < StackCacheBatch-1; i++) | 779 for(i = 0; i < StackCacheBatch-1; i++) |
775 n->batch[i] = (byte*)n + (i+1)*FixedStack; | 780 n->batch[i] = (byte*)n + (i+1)*FixedStack; |
776 } | 781 } |
777 pos = m->stackcachepos; | 782 pos = m->stackcachepos; |
778 for(i = 0; i < StackCacheBatch-1; i++) { | 783 for(i = 0; i < StackCacheBatch-1; i++) { |
(...skipping 13 matching lines...) Expand all Loading... |
792 uint32 i, pos; | 797 uint32 i, pos; |
793 | 798 |
794 pos = (m->stackcachepos - m->stackcachecnt) % StackCacheSize; | 799 pos = (m->stackcachepos - m->stackcachecnt) % StackCacheSize; |
795 n = (StackCacheNode*)m->stackcache[pos]; | 800 n = (StackCacheNode*)m->stackcache[pos]; |
796 pos = (pos + 1) % StackCacheSize; | 801 pos = (pos + 1) % StackCacheSize; |
797 for(i = 0; i < StackCacheBatch-1; i++) { | 802 for(i = 0; i < StackCacheBatch-1; i++) { |
798 n->batch[i] = m->stackcache[pos]; | 803 n->batch[i] = m->stackcache[pos]; |
799 pos = (pos + 1) % StackCacheSize; | 804 pos = (pos + 1) % StackCacheSize; |
800 } | 805 } |
801 m->stackcachecnt -= StackCacheBatch; | 806 m->stackcachecnt -= StackCacheBatch; |
802 » n->pushcnt = 0; | 807 » runtime·lock(&stackcachemu); |
803 » runtime·lfstackpush(&stackcache, n); | 808 » n->next = stackcache; |
| 809 » stackcache = n; |
| 810 » runtime·unlock(&stackcachemu); |
804 } | 811 } |
805 | 812 |
806 void* | 813 void* |
807 runtime·stackalloc(uint32 n) | 814 runtime·stackalloc(uint32 n) |
808 { | 815 { |
809 uint32 pos; | 816 uint32 pos; |
810 void *v; | 817 void *v; |
811 | 818 |
812 // Stackalloc must be called on scheduler stack, so that we | 819 // Stackalloc must be called on scheduler stack, so that we |
813 // never try to grow the stack during the code that stackalloc runs. | 820 // never try to grow the stack during the code that stackalloc runs. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
903 runtime·printf("runtime.SetFinalizer: finalizer already set\n"); | 910 runtime·printf("runtime.SetFinalizer: finalizer already set\n"); |
904 goto throw; | 911 goto throw; |
905 } | 912 } |
906 return; | 913 return; |
907 | 914 |
908 badfunc: | 915 badfunc: |
909 runtime·printf("runtime.SetFinalizer: second argument is %S, not func(%S
)\n", *finalizer.type->string, *obj.type->string); | 916 runtime·printf("runtime.SetFinalizer: second argument is %S, not func(%S
)\n", *finalizer.type->string, *obj.type->string); |
910 throw: | 917 throw: |
911 runtime·throw("runtime.SetFinalizer"); | 918 runtime·throw("runtime.SetFinalizer"); |
912 } | 919 } |
LEFT | RIGHT |