PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
realloc.c
Go to the documentation of this file.
1#include <stdlib.h>
2#include <string.h>
3#include <sys/math.h>
4
5#include "common/heap.h"
6
7#ifdef _KERNEL_
8#include <kernel/log/panic.h>
9#else
10#include <stdio.h>
11#endif
12
13void* realloc(void* ptr, size_t size)
14{
15 if (ptr == NULL)
16 {
17 return malloc(size);
18 }
19
20 if (size == 0)
21 {
22 free(ptr);
23 return NULL;
24 }
25
27
29 if (block->magic != _HEAP_HEADER_MAGIC)
30 {
31#ifdef _KERNEL_
32 panic(NULL, "heap corruption detected in free()");
33#else
34 printf("heap corruption detected in free()\n");
35 abort();
36#endif
37 }
38
39 if (!(block->flags & _HEAP_ALLOCATED))
40 {
41#ifdef _KERNEL_
42 panic(NULL, "double free detected in free()");
43#else
44 printf("double free detected in free()\n");
45 abort();
46#endif
47 }
48
49 uint64_t alignedSize = ROUND_UP(size, _HEAP_ALIGNMENT);
50
51 if (block->flags & _HEAP_MAPPED)
52 {
53 goto direct_alloc;
54 }
55
56 if (alignedSize < block->size)
57 {
58 uint64_t remainder = block->size - alignedSize;
60 {
61 _heap_block_split(block, alignedSize);
62 }
63
65 return ptr;
66 }
67
68 if (alignedSize > block->size)
69 {
70 _heap_header_t* next = CONTAINER_OF_SAFE(block->listEntry.next, _heap_header_t, listEntry);
71
72 if (next != NULL && !(next->flags & _HEAP_ALLOCATED) && (block->data + block->size == (uint8_t*)next))
73 {
74 uint64_t combinedSize = block->size + sizeof(_heap_header_t) + next->size;
75 if (combinedSize >= alignedSize && combinedSize <= _HEAP_LARGE_ALLOC_THRESHOLD)
76 {
77 assert(!(next->flags & _HEAP_MAPPED));
79 block->size = combinedSize;
80 list_remove(&next->listEntry);
81
82 uint64_t remainder = combinedSize - alignedSize;
84 {
85 _heap_block_split(block, alignedSize);
86 }
87
89 return ptr;
90 }
91 }
92 }
93
94direct_alloc:
96 void* newPtr = malloc(size);
97 if (newPtr == NULL)
98 {
99 return NULL;
100 }
101 memcpy(newPtr, ptr, MIN(block->size, size));
102 free(ptr);
103 return newPtr;
104}
#define assert(expression)
Definition assert.h:29
static fd_t data
Definition dwm.c:21
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:292
static void _heap_acquire(void)
Acquire the heap lock.
Definition heap.h:109
#define _HEAP_LARGE_ALLOC_THRESHOLD
Definition heap.h:51
_heap_header_t
Definition heap.h:84
void _heap_block_split(_heap_header_t *block, uint64_t newSize)
Splits a heap block into two blocks, the first of size bytes and the second with the remaining bytes.
Definition heap.c:143
static void _heap_release(void)
Release the heap lock.
Definition heap.h:121
void _heap_remove_from_free_list(_heap_header_t *block)
Removes a block from its free list.
Definition heap.c:184
#define _HEAP_HEADER_MAGIC
Definition heap.h:46
#define _HEAP_ALIGNMENT
Definition heap.h:41
@ _HEAP_ALLOCATED
Block is allocated.
Definition heap.h:63
@ _HEAP_MAPPED
Block is not on the heap, but mapped directly, used for large allocations.
Definition heap.h:64
static void list_remove(list_entry_t *entry)
Removes a list entry from its current list.
Definition list.h:290
#define MIN(x, y)
Definition math.h:18
#define ROUND_UP(number, multiple)
Definition math.h:21
#define NULL
Pointer error value.
Definition NULL.h:25
#define CONTAINER_OF(ptr, type, member)
Container of macro.
#define CONTAINER_OF_SAFE(ptr, type, member)
Safe container of macro.
double remainder(double x, double y)
static atomic_long next
Definition main.c:12
void * realloc(void *ptr, size_t size)
Definition realloc.c:13
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC int printf(const char *_RESTRICT format,...)
Definition printf.c:3
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC _NORETURN void abort(void)
Definition abort.c:9
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:61