ladybird/Kernel/StdLib.cpp
Andreas Kling 60d25f0f4a Kernel: Introduce threads, and refactor everything in support of it.
The scheduler now operates on threads, rather than on processes.
Each process has a main thread, and can have any number of additional
threads. The process exits when the main thread exits.

This patch doesn't actually spawn any additional threads, it merely
does all the plumbing needed to make it possible. :^)
2019-03-23 22:03:17 +01:00

148 lines
3.2 KiB
C++

#include "types.h"
#include "Assertions.h"
#include "kmalloc.h"
#include <AK/StdLibExtras.h>
#include <AK/Types.h>
extern "C" {
void* memcpy(void* dest_ptr, const void* src_ptr, size_t n)
{
if (n >= 1024) {
return mmx_memcpy(dest_ptr, src_ptr, n);
}
size_t dest = (size_t)dest_ptr;
size_t src = (size_t)src_ptr;
// FIXME: Support starting at an unaligned address.
if (!(dest & 0x3) && !(src & 0x3) && n >= 12) {
size_t size_ts = n / sizeof(size_t);
asm volatile(
"rep movsl\n"
: "=S"(src), "=D"(dest)
: "S"(src), "D"(dest), "c"(size_ts)
: "memory"
);
n -= size_ts * sizeof(size_t);
if (n == 0)
return dest_ptr;
}
asm volatile(
"rep movsb\n"
:: "S"(src), "D"(dest), "c"(n)
: "memory"
);
return dest_ptr;
}
void* memmove(void* dest, const void* src, size_t n)
{
if (dest < src)
return memcpy(dest, src, n);
byte *pd = (byte*)dest;
const byte *ps = (const byte*)src;
for (pd += n, ps += n; n--;)
*--pd = *--ps;
return dest;
}
char* strcpy(char* dest, const char *src)
{
auto* dest_ptr = dest;
auto* src_ptr = src;
while ((*dest_ptr++ = *src_ptr++) != '\0');
return dest;
}
char* strncpy(char* dest, const char* src, size_t n)
{
size_t i;
for (i = 0; i < n && src[i] != '\0'; ++i)
dest[i] = src[i];
for ( ; i < n; ++i)
dest[i] = '\0';
return dest;
}
void* memset(void* dest_ptr, int c, size_t n)
{
size_t dest = (size_t)dest_ptr;
// FIXME: Support starting at an unaligned address.
if (!(dest & 0x3) && n >= 12) {
size_t size_ts = n / sizeof(size_t);
size_t expanded_c = (byte)c;
expanded_c |= expanded_c << 8;
expanded_c |= expanded_c << 16;
asm volatile(
"rep stosl\n"
: "=D"(dest)
: "D"(dest), "c"(size_ts), "a"(expanded_c)
: "memory"
);
n -= size_ts * sizeof(size_t);
if (n == 0)
return dest_ptr;
}
asm volatile(
"rep stosb\n"
: "=D" (dest), "=c" (n)
: "0" (dest), "1" (n), "a" (c)
: "memory"
);
return dest_ptr;
}
char* strrchr(const char* str, int ch)
{
char *last = nullptr;
char c;
for (; (c = *str); ++str) {
if (c == ch)
last = const_cast<char*>(str);
}
return last;
}
size_t strlen(const char* str)
{
size_t len = 0;
while (*(str++))
++len;
return len;
}
int strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2; ++s1, ++s2) {
if (*s1 == 0)
return 0;
}
return *(const byte*)s1 < *(const byte*)s2 ? -1 : 1;
}
char* strdup(const char *str)
{
size_t len = strlen(str);
char* new_str = (char*)kmalloc(len + 1);
strcpy(new_str, str);
return new_str;
}
int memcmp(const void* v1, const void* v2, size_t n)
{
auto* s1 = (const byte*)v1;
auto* s2 = (const byte*)v2;
while (n-- > 0) {
if (*s1++ != *s2++)
return s1[-1] < s2[-1] ? -1 : 1;
}
return 0;
}
[[noreturn]] void __cxa_pure_virtual()
{
ASSERT_NOT_REACHED();
}
}