Changes in uspace/lib/c/generic/malloc.c [3e6a98c5:5b46ec8] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/malloc.c
r3e6a98c5 r5b46ec8 67 67 /** Heap shrink granularity 68 68 * 69 * Try not to pump and stress the heap to much69 * Try not to pump and stress the heap too much 70 70 * by shrinking and enlarging it too often. 71 * A heap area won't shr unk if itthe released71 * A heap area won't shrink if the released 72 72 * free block is smaller than this constant. 73 73 * … … 200 200 do { \ 201 201 if (!(expr)) {\ 202 futex_up(&malloc_futex); \202 heap_unlock(); \ 203 203 assert_abort(#expr, __FILE__, __LINE__); \ 204 204 } \ … … 210 210 211 211 #endif /* NDEBUG */ 212 213 214 #ifdef FUTEX_UPGRADABLE 215 /** True if the heap may be accessed from multiple threads. */ 216 static bool multithreaded = false; 217 218 /** Makes accesses to the heap thread safe. */ 219 void malloc_enable_multithreaded(void) 220 { 221 multithreaded = true; 222 } 223 224 /** Serializes access to the heap from multiple threads. */ 225 static inline void heap_lock(void) 226 { 227 if (multithreaded) { 228 futex_down(&malloc_futex); 229 } else { 230 /* 231 * Malloc never switches fibrils while the heap is locked. 232 * Similarly, it never creates new threads from within the 233 * locked region. Therefore, if there are no other threads 234 * except this one, the whole operation will complete without 235 * any interruptions. 236 */ 237 } 238 } 239 240 /** Serializes access to the heap from multiple threads. */ 241 static inline void heap_unlock(void) 242 { 243 if (multithreaded) { 244 futex_up(&malloc_futex); 245 } else { 246 /* 247 * Malloc never switches fibrils while the heap is locked. 248 * Similarly, it never creates new threads from within the 249 * locked region. Therefore, if there are no other threads 250 * except this one, the whole operation will complete without 251 * any interruptions. 252 */ 253 } 254 } 255 256 #else 257 258 /** Makes accesses to the heap thread safe. */ 259 void malloc_enable_multithreaded(void) 260 { 261 /* No-op. Already using thread-safe heap locking operations. */ 262 } 263 264 /** Serializes access to the heap from multiple threads. */ 265 static inline void heap_lock(void) 266 { 267 futex_down(&malloc_futex); 268 } 269 270 /** Serializes access to the heap from multiple threads. */ 271 static inline void heap_unlock(void) 272 { 273 futex_up(&malloc_futex); 274 } 275 #endif 276 212 277 213 278 /** Initialize a heap block … … 289 354 size_t asize = ALIGN_UP(size, PAGE_SIZE); 290 355 void *astart = as_area_create(AS_AREA_ANY, asize, 291 AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE );356 AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE, AS_AREA_UNPAGED); 292 357 if (astart == AS_MAP_FAILED) 293 358 return false; … … 785 850 void *malloc(const size_t size) 786 851 { 787 futex_down(&malloc_futex);852 heap_lock(); 788 853 void *block = malloc_internal(size, BASE_ALIGN); 789 futex_up(&malloc_futex);790 854 heap_unlock(); 855 791 856 return block; 792 857 } … … 807 872 size_t palign = 808 873 1 << (fnzb(max(sizeof(void *), align) - 1) + 1); 809 810 futex_down(&malloc_futex);874 875 heap_lock(); 811 876 void *block = malloc_internal(size, palign); 812 futex_up(&malloc_futex);813 877 heap_unlock(); 878 814 879 return block; 815 880 } … … 828 893 return malloc(size); 829 894 830 futex_down(&malloc_futex);895 heap_lock(); 831 896 832 897 /* Calculate the position of the header. */ … … 863 928 ptr = ((void *) head) + sizeof(heap_block_head_t); 864 929 } else { 930 heap_block_head_t *next_head = 931 (heap_block_head_t *) (((void *) head) + head->size); 932 bool have_next = ((void *) next_head < area->end); 933 934 if (((void *) head) + real_size > area->end) { 935 /* 936 * The current area is too small to hold the resized 937 * block. Make sure there are no used blocks standing 938 * in our way and try to grow the area using real_size 939 * as a safe upper bound. 940 */ 941 942 bool have_next_next; 943 944 if (have_next) { 945 have_next_next = (((void *) next_head) + 946 next_head->size < area->end); 947 } 948 if (!have_next || (next_head->free && !have_next_next)) { 949 /* 950 * There is no next block in this area or 951 * it is a free block and there is no used 952 * block following it. There can't be any 953 * free block following it either as 954 * two free blocks would be merged. 955 */ 956 (void) area_grow(area, real_size); 957 } 958 } 959 865 960 /* 866 961 * Look at the next block. If it is free and the size is 867 * sufficient then merge the two. Otherwise just allocate 868 * a new block, copy the original data into it and869 * free the originalblock.962 * sufficient then merge the two. Otherwise just allocate a new 963 * block, copy the original data into it and free the original 964 * block. 870 965 */ 871 heap_block_head_t *next_head = 872 (heap_block_head_t *) (((void *) head) + head->size); 873 874 if (((void *) next_head < area->end) && 875 (head->size + next_head->size >= real_size) && 876 (next_head->free)) { 966 967 if (have_next && (head->size + next_head->size >= real_size) && 968 next_head->free) { 877 969 block_check(next_head); 878 block_init(head, head->size + next_head->size, false, area); 970 block_init(head, head->size + next_head->size, false, 971 area); 879 972 split_mark(head, real_size); 880 973 881 974 ptr = ((void *) head) + sizeof(heap_block_head_t); 882 975 next_fit = NULL; 883 } else 976 } else { 884 977 reloc = true; 885 } 886 887 futex_up(&malloc_futex); 978 } 979 } 980 981 heap_unlock(); 888 982 889 983 if (reloc) { … … 908 1002 return; 909 1003 910 futex_down(&malloc_futex);1004 heap_lock(); 911 1005 912 1006 /* Calculate the position of the header. */ … … 953 1047 heap_shrink(area); 954 1048 955 futex_up(&malloc_futex);1049 heap_unlock(); 956 1050 } 957 1051 958 1052 void *heap_check(void) 959 1053 { 960 futex_down(&malloc_futex);1054 heap_lock(); 961 1055 962 1056 if (first_heap_area == NULL) { 963 futex_up(&malloc_futex);1057 heap_unlock(); 964 1058 return (void *) -1; 965 1059 } … … 975 1069 (((uintptr_t) area->start % PAGE_SIZE) != 0) || 976 1070 (((uintptr_t) area->end % PAGE_SIZE) != 0)) { 977 futex_up(&malloc_futex);1071 heap_unlock(); 978 1072 return (void *) area; 979 1073 } … … 986 1080 /* Check heap block consistency */ 987 1081 if (head->magic != HEAP_BLOCK_HEAD_MAGIC) { 988 futex_up(&malloc_futex);1082 heap_unlock(); 989 1083 return (void *) head; 990 1084 } … … 994 1088 if ((foot->magic != HEAP_BLOCK_FOOT_MAGIC) || 995 1089 (head->size != foot->size)) { 996 futex_up(&malloc_futex);1090 heap_unlock(); 997 1091 return (void *) foot; 998 1092 } … … 1000 1094 } 1001 1095 1002 futex_up(&malloc_futex);1096 heap_unlock(); 1003 1097 1004 1098 return NULL;
Note:
See TracChangeset
for help on using the changeset viewer.