[all] Remove dependencies on non-freestanding libc

This is the first of two rather big changes to clean up includes
throughout the project. In this commit, the implicit semi-dependency on
libc that bonnibel adds to every module is removed. Previously, I was
sloppy with includes of libc headers and include directory order. Now,
the freestanding headers from libc are split out into libc_free, and an
implicit real dependency is added onto this module, unless `no_libc` is
set to `True`. The full libc needs to be explicitly specified as a
dependency to be used.

Several things needed to change in order to do this:

- Many places use `memset` or `memcpy` that cannot depend on libc. The
  kernel has basic implementations of them itself for this reason. Now
  those functions are moved into the lower-level `j6/memutils.h`, and
  libc merely references them. Other modules are now free to reference
  those functions from libj6 instead.
- The kernel's `assert.h` was renamed kassert.h (matching its `kassert`
  function) so that the new `util/assert.h` can use `__has_include` to
  detect it and make sure the `assert` macro is usable in libutil code.
- Several implementation header files under `__libj6/` also moved under
  the new libc_free.
- A new `include_phase` property has been added to modules for Bonnibel,
  which can be "normal" (default) or "late" which uses `-idirafter`
  instead of `-I` for includes.
- Since `<utility>` and `<new>` are not freestanding, implementations of
  `remove_reference`, `forward`, `move`, and `swap` were added to the
  `util` namespace to replace those from `std`, and `util/new.h` was
  added to declare `operator new` and `operator delete`.
This commit is contained in:
Justin C. Miller
2023-07-12 19:38:31 -07:00
parent a7beb0df18
commit f5208d1641
74 changed files with 233 additions and 210 deletions

View File

@@ -2,13 +2,12 @@
// but should not include the user-specific code.
#ifndef __j6kernel
#include <string.h>
#include <arch/memory.h>
#include <j6/channel.hh>
#include <j6/condition.hh>
#include <j6/errors.h>
#include <j6/flags.h>
#include <j6/memutils.h>
#include <j6/mutex.hh>
#include <j6/syscalls.h>
#include <j6/syslog.hh>

View File

@@ -1,23 +1,10 @@
#pragma once
/** \file j6libc/copy.h
* Internal implementations to aid in implementing mem* functions
*
* This file is part of the C standard library for the jsix operating
* system.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#ifndef __cplusplus
#error "__j6libc/copy.h included by non-C++ code"
#endif
/// \file copy.h
/// Internal implementations to aid in implementing mem* functions
#include <stddef.h>
#include <__j6libc/size_t.h>
namespace __j6libc {
namespace j6 {
template <size_t N>
inline void do_copy(char *s1, const char *s2) {
@@ -52,4 +39,4 @@ inline void do_backward_copy(char *s1, const char *s2, size_t n) {
s1[i] = s2[i];
}
} // namespace __j6libc
} // namespace j6

View File

@@ -8,6 +8,7 @@ j6 = module("j6",
"condition.cpp",
"init.cpp",
"init.s",
"memutils.cpp",
"mutex.cpp",
"protocol_ids.cpp",
"syscalls.s.cog",
@@ -23,6 +24,7 @@ j6 = module("j6",
"j6/flags.h",
"j6/init.h",
"j6/mutex.hh",
"j6/memutils.h",
"j6/protocols.h",
"j6/protocols/service_locator.h",
"j6/syscalls.h.cog",

View File

@@ -0,0 +1,18 @@
#pragma once
/// \file memutils.h
/// Standard mem*() library functions
#include <__j6libc/restrict.h>
#include <__j6libc/size_t.h>
#ifdef __cplusplus
extern "C" {
#endif
void *memcpy(void * restrict s1, const void * restrict s2, size_t n);
void *memmove(void * restrict s1, const void * restrict s2, size_t n);
void *memset(void *s, int c, size_t n);
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,19 +1,35 @@
/** \file memset.cpp
*
* This file is part of the C standard library for the jsix operating
* system.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <string.h>
#include <stddef.h>
#include <j6/memutils.h>
#include <__j6libc/bits.h>
#include <__j6libc/casts.h>
#include "copy.h"
using namespace j6;
using namespace __j6libc;
void *memcpy(void * restrict s1, const void * restrict s2, size_t n) {
asm volatile ("rep movsb" : "+D"(s1), "+S"(s2), "+c"(n) :: "memory");
return s1;
}
static void memmove_dispatch(char *s1, const char *s2, size_t n) {
if (s1 == s2) return;
if (s1 < s2 || s1 > s2 + n)
memcpy(s1, s2, n);
else
do_backward_copy(s1, s2, n);
}
void *memmove(void * restrict s1, const void * restrict s2, size_t n) {
memmove_dispatch(
reinterpret_cast<char*>(s1),
reinterpret_cast<const char*>(s1),
n);
return s1;
}
#if __UINTPTR_WIDTH__ != 64 && __UINTPTR_WIDTH__ != 32
#error "memset: uintptr_t isn't 4 or 8 bytes"
#endif
@@ -28,7 +44,6 @@ static inline uintptr_t repval(uint8_t c) {
return r;
}
void *memset(void *s, int c, size_t n) {
if (!s) return nullptr;
@@ -54,4 +69,4 @@ void *memset(void *s, int c, size_t n) {
*b++ = bval;
return s;
}
}

View File

@@ -2,9 +2,9 @@
// but should not include the user-specific code.
#ifndef __j6kernel
#include <string.h>
#include <j6/errors.h>
#include <j6/flags.h>
#include <j6/memutils.h>
#include <j6/syscalls.h>
#include <j6/thread.hh>

View File

@@ -26,6 +26,7 @@ libc = module("libc",
kind = "lib",
deps = [ "j6" ],
output = "libc.a",
include_phase = "late",
sources = sources,
public_headers = headers,
)

View File

@@ -1,17 +0,0 @@
/** \file memcpy.cpp
*
* This file is part of the C standard library for the jsix operating
* system.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <string.h>
#include <stddef.h>
void *memcpy(void * restrict s1, const void * restrict s2, size_t n) {
asm volatile ("rep movsb" : "+D"(s1), "+S"(s2), "+c"(n) :: "memory");
return s1;
}

View File

@@ -1,33 +0,0 @@
/** \file memmove.cpp
*
* This file is part of the C standard library for the jsix operating
* system.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <string.h>
#include <__j6libc/copy.h>
using namespace __j6libc;
void memmove_dispatch(char *s1, const char *s2, size_t n) {
if (s1 == s2) return;
if (s1 < s2 || s1 > s2 + n)
memcpy(s1, s2, n);
else
do_backward_copy(s1, s2, n);
}
void *memmove(void * restrict s1, const void * restrict s2, size_t n) {
memmove_dispatch(
reinterpret_cast<char*>(s1),
reinterpret_cast<const char*>(s2),
n);
return s1;
}

View File

@@ -0,0 +1,24 @@
# vim: ft=python
libc_free = module("libc_free",
kind = "lib",
no_libc = True,
include_phase = "late",
public_headers = [
'float.h',
'iso646.h',
'limits.h',
'stdalign.h',
'stdarg.h',
'stdbool.h',
'stddef.h',
'stdint.h.cog',
'stdnoreturn.h',
'__j6libc/bits.h',
'__j6libc/casts.h',
'__j6libc/null.h',
'__j6libc/restrict.h',
'__j6libc/size_t.h',
'__j6libc/wchar_t.h',
])

View File

@@ -10,6 +10,7 @@ module("util",
],
public_headers = [
"util/allocator.h",
"util/assert.h",
"util/basic_types.h",
"util/bip_buffer.h",
"util/bitset.h",
@@ -22,6 +23,7 @@ module("util",
"util/linked_list.h",
"util/map.h",
"util/misc.h",
"util/new.h",
"util/no_construct.h",
"util/node_map.h",
"util/pointers.h",

View File

@@ -0,0 +1,13 @@
#pragma once
/// \file assert.h
/// Utility header to include the right assert.h for the environment
#if __has_include("kassert.h")
#include "kassert.h"
#elif __has_include(<assert.h>)
#include <assert.h>
#endif
#if !defined(assert)
#define assert(x) ((void)0)
#endif

View File

@@ -73,4 +73,21 @@ template <unsigned N> struct sized_uint {
using type = typename sized_uint_type<N>::type;
};
template <typename T> struct remove_reference { using type = T; };
template <typename T> struct remove_reference<T&> { using type = T; };
template <typename T> struct remove_reference<T&&> { using type = T; };
} // namespace types
namespace util {
template<typename T>
typename types::remove_reference<T>::type&&
move( T&& x ) { return (typename types::remove_reference<T>::type&&)x; }
template<typename T> T&& forward(typename types::remove_reference<T>::type&& param) { return static_cast<T&&>(param); }
template<typename T> T&& forward(typename types::remove_reference<T>::type& param) { return static_cast<T&&>(param); }
template<typename T> void swap(T &t1, T &t2) { T tmp = move(t1); t1 = move(t2); t2 = move(tmp); }
} // namespace util

View File

@@ -2,9 +2,9 @@
/// \file linked_list.h
/// A generic templatized linked list.
#include <utility>
#include <assert.h>
#include <string.h>
#include <j6/memutils.h>
#include <util/assert.h>
#include <util/basic_types.h>
#include <util/linked_list.h>
namespace util {
@@ -45,7 +45,7 @@ public:
deque(deque &&other) :
m_first {other.m_first},
m_next {other.m_next},
m_list {std::move(other.m_list)} {}
m_list {util::move(other.m_list)} {}
~deque() { clear(); }
@@ -53,7 +53,7 @@ public:
clear();
m_first = other.m_first;
m_next = other.m_next;
m_list = std::move(other.m_list);
m_list = util::move(other.m_list);
return *this;
}

View File

@@ -13,8 +13,8 @@
#include <new>
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <j6/memutils.h>
#include <util/hash.h>
#include <util/vector.h>
#include <util/util.h>

View File

@@ -0,0 +1,14 @@
#pragma once
/// \file new.h
/// Declarations for `operator new` to avoid including <new>
#include <stddef.h>
void *operator new (size_t);
void *operator new [] (size_t);
void *operator new (size_t, void *) noexcept;
void *operator new [] (size_t, void *) noexcept;
void operator delete (void *) noexcept;
void operator delete [] (void *) noexcept;
void operator delete (void *, void *) noexcept;
void operator delete [] (void *, void *) noexcept;

View File

@@ -13,10 +13,10 @@
/// http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/
#include <stdint.h>
#include <string.h>
#include <utility>
#include <j6/memutils.h>
#include <util/allocator.h>
#include <util/basic_types.h>
#include <util/hash.h>
#include <util/util.h>
@@ -118,7 +118,7 @@ public:
node_type new_node;
get_map_key(new_node) = key;
return insert(std::move(new_node));
return insert(util::move(new_node));
}
node_type * find(const key_type &key) {
@@ -150,7 +150,7 @@ public:
key_type &key_at_slot = get_map_key(node_at_slot);
if (open(key_at_slot)) {
node_at_slot = std::move(node);
node_at_slot = util::move(node);
if (!found)
inserted_at = slot;
return m_nodes[inserted_at];
@@ -162,7 +162,7 @@ public:
found = true;
inserted_at = slot;
}
std::swap(node, node_at_slot);
util::swap(node, node_at_slot);
dist = psl_at_slot;
}
@@ -202,7 +202,7 @@ protected:
if (open(next_key) || psl(next_key, next_slot) == 0)
return;
m_nodes[slot] = std::move(next);
m_nodes[slot] = util::move(next);
next.~node_type();
next_key = invalid_id;
++slot;
@@ -236,7 +236,7 @@ protected:
continue;
--m_count;
insert(std::move(node));
insert(util::move(node));
node.~node_type();
key = invalid_id;
}
@@ -297,7 +297,7 @@ public:
bool add(item_type item) {
if (contains(item))
return false;
m_map.insert(std::move(item));
m_map.insert(util::move(item));
return true;
}

View File

@@ -3,7 +3,7 @@
/// Definition of a generic radix_tree structure
#include <stdint.h>
#include <string.h>
#include <j6/memutils.h>
#include <util/util.h>
namespace util {

View File

@@ -2,12 +2,11 @@
/// \file vector.h
/// Definition of a simple dynamic vector collection for use in kernel space
#include <assert.h>
#include <new>
#include <string.h>
#include <utility>
#include <j6/memutils.h>
#include <util/allocator.h>
#include <util/assert.h>
#include <util/basic_types.h>
#include <util/new.h>
#include <util/util.h>
namespace util {
@@ -123,7 +122,7 @@ public:
T & append(T &&item)
{
ensure_capacity(m_size + 1);
m_elements[m_size] = std::move(item);
m_elements[m_size] = util::move(item);
return m_elements[m_size++];
}
@@ -133,7 +132,7 @@ public:
T & emplace(Args&&... args)
{
ensure_capacity(m_size + 1);
new (&m_elements[m_size]) T(std::forward<Args>(args)...);
new (&m_elements[m_size]) T(util::forward<Args>(args)...);
return m_elements[m_size++];
}