Rev 3187 | Rev 3205 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3187 | Rev 3188 | ||
|---|---|---|---|
| Line 107... | Line 107... | ||
| 107 | 107 | ||
| 108 | /* |
108 | /* |
| 109 | * Synchronization primitives used to sleep when there is no memory |
109 | * Synchronization primitives used to sleep when there is no memory |
| 110 | * available. |
110 | * available. |
| 111 | */ |
111 | */ |
| 112 | mutex_t zones_mtx; |
112 | mutex_t mem_avail_mtx; |
| 113 | condvar_t zones_cv; |
113 | condvar_t mem_avail_cv; |
| - | 114 | unsigned long mem_avail_frames = 0; /**< Number of available frames. */ |
|
| 114 | int new_freed_mem = false; |
115 | unsigned long mem_avail_gen = 0; /**< Generation counter. */ |
| 115 | 116 | ||
| 116 | /********************/ |
117 | /********************/ |
| 117 | /* Helper functions */ |
118 | /* Helper functions */ |
| 118 | /********************/ |
119 | /********************/ |
| 119 | 120 | ||
| Line 138... | Line 139... | ||
| 138 | return (frame - zone->frames); |
139 | return (frame - zone->frames); |
| 139 | } |
140 | } |
| 140 | 141 | ||
| 141 | /** Initialize frame structure. |
142 | /** Initialize frame structure. |
| 142 | * |
143 | * |
| 143 | * @param framei Frame structure to be initialized. |
144 | * @param frame Frame structure to be initialized. |
| 144 | */ |
145 | */ |
| 145 | static void frame_initialize(frame_t *frame) |
146 | static void frame_initialize(frame_t *frame) |
| 146 | { |
147 | { |
| 147 | frame->refcount = 1; |
148 | frame->refcount = 1; |
| 148 | frame->buddy_order = 0; |
149 | frame->buddy_order = 0; |
| Line 537... | Line 538... | ||
| 537 | zone->busy_count -= (1 << order); |
538 | zone->busy_count -= (1 << order); |
| 538 | } |
539 | } |
| 539 | } |
540 | } |
| 540 | 541 | ||
| 541 | /** Return frame from zone. */ |
542 | /** Return frame from zone. */ |
| 542 | static frame_t * zone_get_frame(zone_t *zone, index_t frame_idx) |
543 | static frame_t *zone_get_frame(zone_t *zone, index_t frame_idx) |
| 543 | { |
544 | { |
| 544 | ASSERT(frame_idx < zone->count); |
545 | ASSERT(frame_idx < zone->count); |
| 545 | return &zone->frames[frame_idx]; |
546 | return &zone->frames[frame_idx]; |
| 546 | } |
547 | } |
| 547 | 548 | ||
| Line 556... | Line 557... | ||
| 556 | return; |
557 | return; |
| 557 | link = buddy_system_alloc_block(zone->buddy_system, |
558 | link = buddy_system_alloc_block(zone->buddy_system, |
| 558 | &frame->buddy_link); |
559 | &frame->buddy_link); |
| 559 | ASSERT(link); |
560 | ASSERT(link); |
| 560 | zone->free_count--; |
561 | zone->free_count--; |
| - | 562 | ||
| - | 563 | mutex_lock(&mem_avail_mtx); |
|
| - | 564 | mem_avail_frames--; |
|
| - | 565 | mutex_unlock(&mem_avail_mtx); |
|
| 561 | } |
566 | } |
| 562 | 567 | ||
| 563 | /** Join two zones. |
568 | /** Join two zones. |
| 564 | * |
569 | * |
| 565 | * Expect zone_t *z to point to space at least zone_conf_size large. |
570 | * Expect zone_t *z to point to space at least zone_conf_size large. |
| Line 733... | Line 738... | ||
| 733 | spinlock_lock(&zones.lock); |
738 | spinlock_lock(&zones.lock); |
| 734 | 739 | ||
| 735 | if ((z1 >= zones.count) || (z2 >= zones.count)) |
740 | if ((z1 >= zones.count) || (z2 >= zones.count)) |
| 736 | goto errout; |
741 | goto errout; |
| 737 | /* We can join only 2 zones with none existing inbetween */ |
742 | /* We can join only 2 zones with none existing inbetween */ |
| 738 | if (z2-z1 != 1) |
743 | if (z2 - z1 != 1) |
| 739 | goto errout; |
744 | goto errout; |
| 740 | 745 | ||
| 741 | zone1 = zones.info[z1]; |
746 | zone1 = zones.info[z1]; |
| 742 | zone2 = zones.info[z2]; |
747 | zone2 = zones.info[z2]; |
| 743 | spinlock_lock(&zone1->lock); |
748 | spinlock_lock(&zone1->lock); |
| Line 794... | Line 799... | ||
| 794 | void zone_merge_all(void) |
799 | void zone_merge_all(void) |
| 795 | { |
800 | { |
| 796 | int count = zones.count; |
801 | int count = zones.count; |
| 797 | 802 | ||
| 798 | while (zones.count > 1 && --count) { |
803 | while (zones.count > 1 && --count) { |
| 799 | zone_merge(0,1); |
804 | zone_merge(0, 1); |
| 800 | break; |
805 | break; |
| 801 | } |
806 | } |
| 802 | } |
807 | } |
| 803 | 808 | ||
| 804 | /** Create new frame zone. |
809 | /** Create new frame zone. |
| Line 891... | Line 896... | ||
| 891 | ASSERT(confframe); |
896 | ASSERT(confframe); |
| 892 | /* If conframe is supposed to be inside our zone, then make sure |
897 | /* If conframe is supposed to be inside our zone, then make sure |
| 893 | * it does not span kernel & init |
898 | * it does not span kernel & init |
| 894 | */ |
899 | */ |
| 895 | confcount = SIZE2FRAMES(zone_conf_size(count)); |
900 | confcount = SIZE2FRAMES(zone_conf_size(count)); |
| 896 | if (confframe >= start && confframe < start+count) { |
901 | if (confframe >= start && confframe < start + count) { |
| 897 | for (;confframe < start + count; confframe++) { |
902 | for (; confframe < start + count; confframe++) { |
| 898 | addr = PFN2ADDR(confframe); |
903 | addr = PFN2ADDR(confframe); |
| 899 | if (overlaps(addr, PFN2ADDR(confcount), |
904 | if (overlaps(addr, PFN2ADDR(confcount), |
| 900 | KA2PA(config.base), config.kernel_size)) |
905 | KA2PA(config.base), config.kernel_size)) |
| 901 | continue; |
906 | continue; |
| 902 | 907 | ||
| Line 926... | Line 931... | ||
| 926 | zone_construct(start, count, z, flags); |
931 | zone_construct(start, count, z, flags); |
| 927 | znum = zones_add_zone(z); |
932 | znum = zones_add_zone(z); |
| 928 | if (znum == -1) |
933 | if (znum == -1) |
| 929 | return -1; |
934 | return -1; |
| 930 | 935 | ||
| - | 936 | mutex_lock(&mem_avail_mtx); |
|
| - | 937 | mem_avail_frames += count; |
|
| - | 938 | mutex_unlock(&mem_avail_mtx); |
|
| - | 939 | ||
| 931 | /* If confdata in zone, mark as unavailable */ |
940 | /* If confdata in zone, mark as unavailable */ |
| 932 | if (confframe >= start && confframe < start + count) |
941 | if (confframe >= start && confframe < start + count) |
| 933 | for (i = confframe; i < confframe + confcount; i++) { |
942 | for (i = confframe; i < confframe + confcount; i++) { |
| 934 | zone_mark_unavailable(z, i - z->base); |
943 | zone_mark_unavailable(z, i - z->base); |
| 935 | } |
944 | } |
| - | 945 | ||
| 936 | return znum; |
946 | return znum; |
| 937 | } |
947 | } |
| 938 | 948 | ||
| 939 | /***************************************/ |
949 | /***************************************/ |
| 940 | /* Frame functions */ |
950 | /* Frame functions */ |
| Line 944... | Line 954... | ||
| 944 | { |
954 | { |
| 945 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
955 | zone_t *zone = find_zone_and_lock(pfn, &hint); |
| 946 | 956 | ||
| 947 | ASSERT(zone); |
957 | ASSERT(zone); |
| 948 | 958 | ||
| 949 | zone_get_frame(zone, pfn-zone->base)->parent = data; |
959 | zone_get_frame(zone, pfn - zone->base)->parent = data; |
| 950 | spinlock_unlock(&zone->lock); |
960 | spinlock_unlock(&zone->lock); |
| 951 | } |
961 | } |
| 952 | 962 | ||
| 953 | void *frame_get_parent(pfn_t pfn, unsigned int hint) |
963 | void *frame_get_parent(pfn_t pfn, unsigned int hint) |
| 954 | { |
964 | { |
| Line 975... | Line 985... | ||
| 975 | { |
985 | { |
| 976 | ipl_t ipl; |
986 | ipl_t ipl; |
| 977 | int freed; |
987 | int freed; |
| 978 | pfn_t v; |
988 | pfn_t v; |
| 979 | zone_t *zone; |
989 | zone_t *zone; |
| - | 990 | unsigned long gen = 0; |
|
| 980 | 991 | ||
| 981 | loop: |
992 | loop: |
| 982 | ipl = interrupts_disable(); |
993 | ipl = interrupts_disable(); |
| 983 | 994 | ||
| 984 | /* |
995 | /* |
| Line 1006... | Line 1017... | ||
| 1006 | interrupts_restore(ipl); |
1017 | interrupts_restore(ipl); |
| 1007 | return 0; |
1018 | return 0; |
| 1008 | } |
1019 | } |
| 1009 | 1020 | ||
| 1010 | #ifdef CONFIG_DEBUG |
1021 | #ifdef CONFIG_DEBUG |
| - | 1022 | unsigned long avail; |
|
| - | 1023 | ||
| - | 1024 | mutex_lock(&mem_avail_mtx); |
|
| - | 1025 | avail = mem_avail_frames; |
|
| - | 1026 | mutex_unlock(&mem_avail_mtx); |
|
| - | 1027 | ||
| 1011 | printf("Thread %" PRIu64 " falling asleep, low memory.\n", THREAD->tid); |
1028 | printf("Thread %" PRIu64 " waiting for %u frames, " |
| - | 1029 | "%u available.\n", THREAD->tid, 1ULL << order, avail); |
|
| 1012 | #endif |
1030 | #endif |
| 1013 | 1031 | ||
| 1014 | mutex_lock(&zones_mtx); |
1032 | mutex_lock(&mem_avail_mtx); |
| - | 1033 | while ((mem_avail_frames < (1ULL << order)) || |
|
| 1015 | if (!new_freed_mem) |
1034 | gen == mem_avail_gen) |
| 1016 | condvar_wait(&zones_cv, &zones_mtx); |
1035 | condvar_wait(&mem_avail_cv, &mem_avail_mtx); |
| 1017 | new_freed_mem = false; |
1036 | gen = mem_avail_gen; |
| 1018 | mutex_unlock(&zones_mtx); |
1037 | mutex_unlock(&mem_avail_mtx); |
| 1019 | 1038 | ||
| 1020 | #ifdef CONFIG_DEBUG |
1039 | #ifdef CONFIG_DEBUG |
| - | 1040 | mutex_lock(&mem_avail_mtx); |
|
| - | 1041 | avail = mem_avail_frames; |
|
| - | 1042 | mutex_unlock(&mem_avail_mtx); |
|
| - | 1043 | ||
| 1021 | printf("Thread %" PRIu64 " woken up, memory available.\n", THREAD->tid); |
1044 | printf("Thread %" PRIu64 " woken up, %u frames available.\n", |
| - | 1045 | THREAD->tid, avail); |
|
| 1022 | #endif |
1046 | #endif |
| 1023 | 1047 | ||
| 1024 | interrupts_restore(ipl); |
1048 | interrupts_restore(ipl); |
| 1025 | goto loop; |
1049 | goto loop; |
| 1026 | } |
1050 | } |
| 1027 | 1051 | ||
| 1028 | v = zone_frame_alloc(zone, order); |
1052 | v = zone_frame_alloc(zone, order); |
| 1029 | v += zone->base; |
1053 | v += zone->base; |
| 1030 | 1054 | ||
| 1031 | spinlock_unlock(&zone->lock); |
1055 | spinlock_unlock(&zone->lock); |
| - | 1056 | ||
| - | 1057 | mutex_lock(&mem_avail_mtx); |
|
| - | 1058 | mem_avail_frames -= (1ULL << order); |
|
| - | 1059 | mutex_unlock(&mem_avail_mtx); |
|
| - | 1060 | ||
| 1032 | interrupts_restore(ipl); |
1061 | interrupts_restore(ipl); |
| 1033 | 1062 | ||
| 1034 | if (flags & FRAME_KA) |
1063 | if (flags & FRAME_KA) |
| 1035 | return (void *)PA2KA(PFN2ADDR(v)); |
1064 | return (void *)PA2KA(PFN2ADDR(v)); |
| 1036 | return (void *)PFN2ADDR(v); |
1065 | return (void *)PFN2ADDR(v); |
| Line 1063... | Line 1092... | ||
| 1063 | spinlock_unlock(&zone->lock); |
1092 | spinlock_unlock(&zone->lock); |
| 1064 | 1093 | ||
| 1065 | /* |
1094 | /* |
| 1066 | * Signal that some memory has been freed. |
1095 | * Signal that some memory has been freed. |
| 1067 | */ |
1096 | */ |
| 1068 | mutex_lock(&zones_mtx); |
1097 | mutex_lock(&mem_avail_mtx); |
| 1069 | new_freed_mem = true; |
1098 | mem_avail_frames++; |
| - | 1099 | mem_avail_gen++; |
|
| 1070 | condvar_broadcast(&zones_cv); |
1100 | condvar_broadcast(&mem_avail_cv); |
| 1071 | mutex_unlock(&zones_mtx); |
1101 | mutex_unlock(&mem_avail_mtx); |
| 1072 | 1102 | ||
| 1073 | interrupts_restore(ipl); |
1103 | interrupts_restore(ipl); |
| 1074 | } |
1104 | } |
| 1075 | 1105 | ||
| 1076 | /** Add reference to frame. |
1106 | /** Add reference to frame. |
| Line 1122... | Line 1152... | ||
| 1122 | void frame_init(void) |
1152 | void frame_init(void) |
| 1123 | { |
1153 | { |
| 1124 | if (config.cpu_active == 1) { |
1154 | if (config.cpu_active == 1) { |
| 1125 | zones.count = 0; |
1155 | zones.count = 0; |
| 1126 | spinlock_initialize(&zones.lock, "zones.lock"); |
1156 | spinlock_initialize(&zones.lock, "zones.lock"); |
| - | 1157 | mutex_initialize(&mem_avail_mtx, MUTEX_ACTIVE); |
|
| - | 1158 | condvar_initialize(&mem_avail_cv); |
|
| 1127 | } |
1159 | } |
| 1128 | /* Tell the architecture to create some memory */ |
1160 | /* Tell the architecture to create some memory */ |
| 1129 | frame_arch_init(); |
1161 | frame_arch_init(); |
| 1130 | if (config.cpu_active == 1) { |
1162 | if (config.cpu_active == 1) { |
| 1131 | frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)), |
1163 | frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)), |
| Line 1146... | Line 1178... | ||
| 1146 | 1178 | ||
| 1147 | /* Black list first frame, as allocating NULL would |
1179 | /* Black list first frame, as allocating NULL would |
| 1148 | * fail in some places */ |
1180 | * fail in some places */ |
| 1149 | frame_mark_unavailable(0, 1); |
1181 | frame_mark_unavailable(0, 1); |
| 1150 | } |
1182 | } |
| 1151 | - | ||
| 1152 | mutex_initialize(&zones_mtx, MUTEX_ACTIVE); /* mimic spinlock */ |
- | |
| 1153 | condvar_initialize(&zones_cv); |
- | |
| 1154 | } |
1183 | } |
| 1155 | 1184 | ||
| 1156 | 1185 | ||
| 1157 | /** Return total size of all zones. */ |
1186 | /** Return total size of all zones. */ |
| 1158 | uint64_t zone_total_size(void) |
1187 | uint64_t zone_total_size(void) |