Changes in uspace/lib/c/generic/malloc.c [5b46ec8:3e6a98c5] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/malloc.c
r5b46ec8 r3e6a98c5 67 67 /** Heap shrink granularity 68 68 * 69 * Try not to pump and stress the heap to omuch69 * Try not to pump and stress the heap to much 70 70 * by shrinking and enlarging it too often. 71 * A heap area won't shr ink ifthe released71 * A heap area won't shrunk if it the released 72 72 * free block is smaller than this constant. 73 73 * … … 200 200 do { \ 201 201 if (!(expr)) {\ 202 heap_unlock(); \202 futex_up(&malloc_futex); \ 203 203 assert_abort(#expr, __FILE__, __LINE__); \ 204 204 } \ … … 210 210 211 211 #endif /* NDEBUG */ 212 213 214 #ifdef FUTEX_UPGRADABLE215 /** 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 the233 * locked region. Therefore, if there are no other threads234 * except this one, the whole operation will complete without235 * 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 the249 * locked region. Therefore, if there are no other threads250 * except this one, the whole operation will complete without251 * any interruptions.252 */253 }254 }255 256 #else257 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 #endif276 277 212 278 213 /** Initialize a heap block … … 354 289 size_t asize = ALIGN_UP(size, PAGE_SIZE); 355 290 void *astart = as_area_create(AS_AREA_ANY, asize, 356 AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE , AS_AREA_UNPAGED);291 AS_AREA_WRITE | AS_AREA_READ | AS_AREA_CACHEABLE); 357 292 if (astart == AS_MAP_FAILED) 358 293 return false; … … 850 785 void *malloc(const size_t size) 851 786 { 852 heap_lock();787 futex_down(&malloc_futex); 853 788 void *block = malloc_internal(size, BASE_ALIGN); 854 heap_unlock();855 789 futex_up(&malloc_futex); 790 856 791 return block; 857 792 } … … 872 807 size_t palign = 873 808 1 << (fnzb(max(sizeof(void *), align) - 1) + 1); 874 875 heap_lock();809 810 futex_down(&malloc_futex); 876 811 void *block = malloc_internal(size, palign); 877 heap_unlock();878 812 futex_up(&malloc_futex); 813 879 814 return block; 880 815 } … … 893 828 return malloc(size); 894 829 895 heap_lock();830 futex_down(&malloc_futex); 896 831 897 832 /* Calculate the position of the header. */ … … 928 863 ptr = ((void *) head) + sizeof(heap_block_head_t); 929 864 } else { 865 /* 866 * 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 and 869 * free the original block. 870 */ 930 871 heap_block_head_t *next_head = 931 872 (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 960 /* 961 * Look at the next block. If it is free and the size is 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. 965 */ 966 967 if (have_next && (head->size + next_head->size >= real_size) && 968 next_head->free) { 873 874 if (((void *) next_head < area->end) && 875 (head->size + next_head->size >= real_size) && 876 (next_head->free)) { 969 877 block_check(next_head); 970 block_init(head, head->size + next_head->size, false, 971 area); 878 block_init(head, head->size + next_head->size, false, area); 972 879 split_mark(head, real_size); 973 880 974 881 ptr = ((void *) head) + sizeof(heap_block_head_t); 975 882 next_fit = NULL; 976 } else {883 } else 977 884 reloc = true; 978 } 979 } 980 981 heap_unlock(); 885 } 886 887 futex_up(&malloc_futex); 982 888 983 889 if (reloc) { … … 1002 908 return; 1003 909 1004 heap_lock();910 futex_down(&malloc_futex); 1005 911 1006 912 /* Calculate the position of the header. */ … … 1047 953 heap_shrink(area); 1048 954 1049 heap_unlock();955 futex_up(&malloc_futex); 1050 956 } 1051 957 1052 958 void *heap_check(void) 1053 959 { 1054 heap_lock();960 futex_down(&malloc_futex); 1055 961 1056 962 if (first_heap_area == NULL) { 1057 heap_unlock();963 futex_up(&malloc_futex); 1058 964 return (void *) -1; 1059 965 } … … 1069 975 (((uintptr_t) area->start % PAGE_SIZE) != 0) || 1070 976 (((uintptr_t) area->end % PAGE_SIZE) != 0)) { 1071 heap_unlock();977 futex_up(&malloc_futex); 1072 978 return (void *) area; 1073 979 } … … 1080 986 /* Check heap block consistency */ 1081 987 if (head->magic != HEAP_BLOCK_HEAD_MAGIC) { 1082 heap_unlock();988 futex_up(&malloc_futex); 1083 989 return (void *) head; 1084 990 } … … 1088 994 if ((foot->magic != HEAP_BLOCK_FOOT_MAGIC) || 1089 995 (head->size != foot->size)) { 1090 heap_unlock();996 futex_up(&malloc_futex); 1091 997 return (void *) foot; 1092 998 } … … 1094 1000 } 1095 1001 1096 heap_unlock();1002 futex_up(&malloc_futex); 1097 1003 1098 1004 return NULL;
Note:
See TracChangeset
for help on using the changeset viewer.