Rev 3187 | Rev 3205 | Go to most recent revision | Show entire file | Regard 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 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 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 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) |