mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-15 23:17:14 +00:00
libc: remove global constructors
- readv_writev: move 'rw_lock' instance into a function scope, constructing the instance on the first access. - select: move 'select_cb_list' instance into function scope. - thread: move 'key_list_lock' and 'keys' into function scope. - rwlock, semaphore, socket_fs_plugin, thread, thread_create: instantiate 'Libc::Allocator' per use, alleviating the need for a global instance. Issue #3496
This commit is contained in:
parent
4a7b0e99a6
commit
0aedabd245
@ -23,9 +23,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static Genode::Lock rw_lock;
|
||||
|
||||
|
||||
struct Read
|
||||
{
|
||||
ssize_t operator()(int fd, void *buf, size_t count)
|
||||
@ -44,10 +41,17 @@ struct Write
|
||||
};
|
||||
|
||||
|
||||
static Genode::Lock &rw_lock()
|
||||
{
|
||||
static Genode::Lock rw_lock;
|
||||
return rw_lock;
|
||||
}
|
||||
|
||||
|
||||
template <typename Rw_func>
|
||||
static ssize_t readv_writev_impl(Rw_func rw_func, int fd, const struct iovec *iov, int iovcnt)
|
||||
{
|
||||
Genode::Lock_guard<Genode::Lock> rw_lock_guard(rw_lock);
|
||||
Genode::Lock_guard<Genode::Lock> rw_lock_guard(rw_lock());
|
||||
|
||||
char *v;
|
||||
ssize_t bytes_transfered_total = 0;
|
||||
|
@ -24,9 +24,6 @@
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static Libc::Allocator object_alloc;
|
||||
|
||||
|
||||
/*
|
||||
* A reader-preferring implementation of a readers-writer lock as described
|
||||
* in Michael Raynal, "Concurrent Programming: Algorithms, Principles, and
|
||||
@ -105,7 +102,8 @@ extern "C" {
|
||||
|
||||
try {
|
||||
Genode::Lock::Guard g(rwlock_init_lock);
|
||||
*rwlock = new (object_alloc) struct pthread_rwlock();
|
||||
Libc::Allocator alloc { };
|
||||
*rwlock = new (alloc) struct pthread_rwlock();
|
||||
return 0;
|
||||
} catch (...) { return ENOMEM; }
|
||||
}
|
||||
@ -117,7 +115,8 @@ extern "C" {
|
||||
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
|
||||
{
|
||||
destroy(object_alloc, *rwlock);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, *rwlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -154,7 +153,8 @@ extern "C" {
|
||||
|
||||
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
|
||||
{
|
||||
*attr = new (object_alloc) struct pthread_rwlockattr();
|
||||
Libc::Allocator alloc { };
|
||||
*attr = new (alloc) struct pthread_rwlockattr();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -175,7 +175,8 @@ extern "C" {
|
||||
|
||||
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)
|
||||
{
|
||||
destroy(object_alloc, *attr);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, *attr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ struct Libc::Select_cb_list
|
||||
|
||||
struct Guard : Genode::Lock::Guard
|
||||
{
|
||||
Select_cb_list *l;
|
||||
Select_cb_list *l;
|
||||
|
||||
Guard(Select_cb_list &list) : Genode::Lock::Guard(list._mutex), l(&list) { }
|
||||
};
|
||||
@ -110,7 +110,11 @@ Select_cb_list *l;
|
||||
};
|
||||
|
||||
/** The global list of tasks waiting for select */
|
||||
static Libc::Select_cb_list select_cb_list;
|
||||
static Libc::Select_cb_list &select_cb_list()
|
||||
{
|
||||
static Libc::Select_cb_list inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -183,7 +187,7 @@ static void select_notify()
|
||||
/* check for each waiting select() function if one of its fds is ready now
|
||||
* and if so, wake all up */
|
||||
|
||||
select_cb_list.for_each([&] (Libc::Select_cb &scb) {
|
||||
select_cb_list().for_each([&] (Libc::Select_cb &scb) {
|
||||
scb.nready = selscan(scb.nfds,
|
||||
&scb.readfds, &scb.writefds, &scb.exceptfds,
|
||||
&tmp_readfds, &tmp_writefds, &tmp_exceptfds);
|
||||
@ -236,7 +240,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
* We use the guard directly to atomically check if any descripor is
|
||||
* ready, but insert into select-callback list otherwise.
|
||||
*/
|
||||
Libc::Select_cb_list::Guard guard(select_cb_list);
|
||||
Libc::Select_cb_list::Guard guard(select_cb_list());
|
||||
|
||||
int const nready = selscan(nfds,
|
||||
&in_readfds, &in_writefds, &in_exceptfds,
|
||||
@ -254,7 +258,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
|
||||
select_cb.construct(nfds, in_readfds, in_writefds, in_exceptfds);
|
||||
|
||||
select_cb_list.unsynchronized_insert(&(*select_cb));
|
||||
select_cb_list().unsynchronized_insert(&(*select_cb));
|
||||
}
|
||||
|
||||
struct Timeout
|
||||
@ -283,7 +287,7 @@ int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||
while (!timeout.expired() && select_cb->nready == 0)
|
||||
timeout.duration = Libc::suspend(check, timeout.duration);
|
||||
|
||||
select_cb_list.remove(&(*select_cb));
|
||||
select_cb_list().remove(&(*select_cb));
|
||||
|
||||
if (timeout.expired())
|
||||
return 0;
|
||||
@ -352,14 +356,14 @@ int Libc::Select_handler_base::select(int nfds, fd_set &readfds,
|
||||
|
||||
/* remove potentially enqueued callback from list */
|
||||
if (_select_cb->constructed())
|
||||
select_cb_list.remove(&(**_select_cb));
|
||||
select_cb_list().remove(&(**_select_cb));
|
||||
|
||||
{
|
||||
/*
|
||||
* We use the guard directly to atomically check is any descripor is
|
||||
* ready, and insert into select-callback list otherwise.
|
||||
*/
|
||||
Libc::Select_cb_list::Guard guard(select_cb_list);
|
||||
Libc::Select_cb_list::Guard guard(select_cb_list());
|
||||
|
||||
int const nready = selscan(nfds,
|
||||
&in_readfds, &in_writefds, &in_exceptfds,
|
||||
@ -373,7 +377,7 @@ int Libc::Select_handler_base::select(int nfds, fd_set &readfds,
|
||||
|
||||
_select_cb->construct(nfds, in_readfds, in_writefds, in_exceptfds);
|
||||
|
||||
select_cb_list.unsynchronized_insert(&(**_select_cb));
|
||||
select_cb_list().unsynchronized_insert(&(**_select_cb));
|
||||
}
|
||||
|
||||
Libc::schedule_select(this);
|
||||
@ -388,7 +392,7 @@ void Libc::Select_handler_base::dispatch_select()
|
||||
|
||||
if (select_cb->nready == 0) return;
|
||||
|
||||
select_cb_list.remove(&(*select_cb));
|
||||
select_cb_list().remove(&(*select_cb));
|
||||
Libc::schedule_select(nullptr);
|
||||
|
||||
select_ready(select_cb->nready, select_cb->readfds,
|
||||
|
@ -20,8 +20,6 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static Libc::Allocator object_alloc;
|
||||
|
||||
extern "C" {
|
||||
|
||||
/*
|
||||
@ -43,7 +41,8 @@ extern "C" {
|
||||
|
||||
int sem_destroy(sem_t *sem)
|
||||
{
|
||||
destroy(object_alloc, *sem);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, *sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -57,7 +56,8 @@ extern "C" {
|
||||
|
||||
int sem_init(sem_t *sem, int pshared, unsigned int value)
|
||||
{
|
||||
*sem = new (object_alloc) struct sem(value);
|
||||
Libc::Allocator alloc { };
|
||||
*sem = new (alloc) struct sem(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,6 @@ namespace Libc {
|
||||
|
||||
namespace Socket_fs {
|
||||
|
||||
Libc::Allocator global_allocator;
|
||||
|
||||
using Libc::Errno;
|
||||
|
||||
struct Absolute_path : Vfs::Absolute_path
|
||||
@ -542,7 +540,8 @@ extern "C" int socket_fs_accept(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
||||
|
||||
Socket_fs::Context *accept_context;
|
||||
try {
|
||||
accept_context = new (&global_allocator)
|
||||
Libc::Allocator alloc { };
|
||||
accept_context = new (alloc)
|
||||
Socket_fs::Context(listen_context->proto(), handle_fd);
|
||||
} catch (New_socket_failed) { return Errno(EACCES); }
|
||||
|
||||
@ -962,7 +961,8 @@ extern "C" int socket_fs_socket(int domain, int type, int protocol)
|
||||
Genode::error("failed to open new socket at ", path);
|
||||
return Errno(EACCES);
|
||||
}
|
||||
context = new (&global_allocator)
|
||||
Libc::Allocator alloc { };
|
||||
context = new (alloc)
|
||||
Socket_fs::Context(proto, handle_fd);
|
||||
} catch (New_socket_failed) { return Errno(EACCES); }
|
||||
|
||||
@ -1004,9 +1004,10 @@ extern "C" int getifaddrs(struct ifaddrs **ifap)
|
||||
static sockaddr_in address;
|
||||
static sockaddr_in netmask { 0 };
|
||||
static sockaddr_in broadcast { 0 };
|
||||
static char name[1] { };
|
||||
|
||||
static ifaddrs ifaddr {
|
||||
.ifa_name = "",
|
||||
.ifa_name = name,
|
||||
.ifa_flags = IFF_UP,
|
||||
.ifa_addr = (sockaddr*)&address,
|
||||
.ifa_netmask = (sockaddr*)&netmask,
|
||||
@ -1188,7 +1189,8 @@ int Socket_fs::Plugin::close(Libc::File_descriptor *fd)
|
||||
Socket_fs::Context *context = dynamic_cast<Socket_fs::Context *>(fd->context);
|
||||
if (!context) return Errno(EBADF);
|
||||
|
||||
Genode::destroy(&global_allocator, context);
|
||||
Libc::Allocator alloc { };
|
||||
Genode::destroy(alloc, context);
|
||||
Libc::file_descriptor_allocator()->free(fd);
|
||||
|
||||
/*
|
||||
|
@ -29,14 +29,17 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
static Libc::Allocator object_alloc;
|
||||
|
||||
|
||||
static Env *_env_ptr; /* solely needed to spawn the timeout thread for the
|
||||
timed semaphore */
|
||||
|
||||
static Thread *_main_thread_ptr;
|
||||
|
||||
void Libc::init_pthread_support(Genode::Env &env) { _env_ptr = &env; }
|
||||
|
||||
void Libc::init_pthread_support(Genode::Env &env)
|
||||
{
|
||||
_env_ptr = &env;
|
||||
_main_thread_ptr = Thread::myself();
|
||||
}
|
||||
|
||||
|
||||
static Libc::Timeout_entrypoint &_global_timeout_ep()
|
||||
@ -50,19 +53,6 @@ static Libc::Timeout_entrypoint &_global_timeout_ep()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We initialize the main-thread pointer in a constructor depending on the
|
||||
* assumption that libpthread is loaded on application startup by ldso. During
|
||||
* this stage only the main thread is executed.
|
||||
*/
|
||||
static __attribute__((constructor)) Thread * main_thread()
|
||||
{
|
||||
static Thread *thread = Thread::myself();
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* pthread
|
||||
*/
|
||||
@ -172,7 +162,8 @@ extern "C" {
|
||||
{
|
||||
thread->join(retval);
|
||||
|
||||
destroy(object_alloc, thread);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -183,7 +174,8 @@ extern "C" {
|
||||
if (!attr)
|
||||
return EINVAL;
|
||||
|
||||
*attr = new (object_alloc) pthread_attr;
|
||||
Libc::Allocator alloc { };
|
||||
*attr = new (alloc) pthread_attr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -194,7 +186,8 @@ extern "C" {
|
||||
if (!attr || !*attr)
|
||||
return EINVAL;
|
||||
|
||||
destroy(object_alloc, *attr);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, *attr);
|
||||
*attr = 0;
|
||||
|
||||
return 0;
|
||||
@ -218,7 +211,7 @@ extern "C" {
|
||||
/* special non-POSIX function (for example used in libresolv) */
|
||||
int _pthread_main_np(void)
|
||||
{
|
||||
return (Thread::myself() == main_thread());
|
||||
return (Thread::myself() == _main_thread_ptr);
|
||||
}
|
||||
|
||||
|
||||
@ -251,7 +244,8 @@ extern "C" {
|
||||
* of the pthread object would also destruct the 'Thread' of the main
|
||||
* thread.
|
||||
*/
|
||||
static pthread *main = new (object_alloc) pthread(*Thread::myself());
|
||||
Libc::Allocator alloc { };
|
||||
static pthread *main = new (alloc) pthread(*Thread::myself());
|
||||
return main;
|
||||
}
|
||||
|
||||
@ -498,7 +492,8 @@ extern "C" {
|
||||
if (!attr)
|
||||
return EINVAL;
|
||||
|
||||
*attr = new (object_alloc) pthread_mutex_attr;
|
||||
Libc::Allocator alloc { };
|
||||
*attr = new (alloc) pthread_mutex_attr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -509,7 +504,8 @@ extern "C" {
|
||||
if (!attr || !*attr)
|
||||
return EINVAL;
|
||||
|
||||
destroy(object_alloc, *attr);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, *attr);
|
||||
*attr = 0;
|
||||
|
||||
return 0;
|
||||
@ -533,7 +529,8 @@ extern "C" {
|
||||
if (!mutex)
|
||||
return EINVAL;
|
||||
|
||||
*mutex = new (object_alloc) pthread_mutex(attr);
|
||||
Libc::Allocator alloc { };
|
||||
*mutex = new (alloc) pthread_mutex(attr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -544,7 +541,8 @@ extern "C" {
|
||||
if ((!mutex) || (*mutex == PTHREAD_MUTEX_INITIALIZER))
|
||||
return EINVAL;
|
||||
|
||||
destroy(object_alloc, *mutex);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, *mutex);
|
||||
*mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
return 0;
|
||||
@ -655,7 +653,8 @@ extern "C" {
|
||||
|
||||
try {
|
||||
Genode::Lock::Guard g(cond_init_lock);
|
||||
*cond = new (object_alloc) pthread_cond;
|
||||
Libc::Allocator alloc { };
|
||||
*cond = new (alloc) pthread_cond;
|
||||
return 0;
|
||||
} catch (...) { return ENOMEM; }
|
||||
}
|
||||
@ -673,7 +672,8 @@ extern "C" {
|
||||
if (!cond || !*cond)
|
||||
return EINVAL;
|
||||
|
||||
destroy(object_alloc, *cond);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, *cond);
|
||||
*cond = 0;
|
||||
|
||||
return 0;
|
||||
@ -838,24 +838,42 @@ extern "C" {
|
||||
};
|
||||
|
||||
|
||||
static Lock key_list_lock;
|
||||
List<Key_element> key_list[PTHREAD_KEYS_MAX];
|
||||
static Lock &key_list_lock()
|
||||
{
|
||||
static Lock inst { };
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
struct Keys
|
||||
{
|
||||
List<Key_element> key[PTHREAD_KEYS_MAX];
|
||||
};
|
||||
|
||||
|
||||
static Keys &keys()
|
||||
{
|
||||
static Keys inst { };
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
||||
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*))
|
||||
{
|
||||
if (!key)
|
||||
return EINVAL;
|
||||
|
||||
Lock_guard<Lock> key_list_lock_guard(key_list_lock);
|
||||
Lock_guard<Lock> key_list_lock_guard(key_list_lock());
|
||||
|
||||
for (int k = 0; k < PTHREAD_KEYS_MAX; k++) {
|
||||
/*
|
||||
* Find an empty key slot and insert an element for the current
|
||||
* thread to mark the key slot as used.
|
||||
*/
|
||||
if (!key_list[k].first()) {
|
||||
Key_element *key_element = new (object_alloc) Key_element(Thread::myself(), 0);
|
||||
key_list[k].insert(key_element);
|
||||
if (!keys().key[k].first()) {
|
||||
Libc::Allocator alloc { };
|
||||
Key_element *key_element = new (alloc) Key_element(Thread::myself(), 0);
|
||||
keys().key[k].insert(key_element);
|
||||
*key = k;
|
||||
return 0;
|
||||
}
|
||||
@ -867,14 +885,15 @@ extern "C" {
|
||||
|
||||
int pthread_key_delete(pthread_key_t key)
|
||||
{
|
||||
if (key < 0 || key >= PTHREAD_KEYS_MAX || !key_list[key].first())
|
||||
if (key < 0 || key >= PTHREAD_KEYS_MAX || !keys().key[key].first())
|
||||
return EINVAL;
|
||||
|
||||
Lock_guard<Lock> key_list_lock_guard(key_list_lock);
|
||||
Lock_guard<Lock> key_list_lock_guard(key_list_lock());
|
||||
|
||||
while (Key_element * element = key_list[key].first()) {
|
||||
key_list[key].remove(element);
|
||||
destroy(object_alloc, element);
|
||||
while (Key_element * element = keys().key[key].first()) {
|
||||
keys().key[key].remove(element);
|
||||
Libc::Allocator alloc { };
|
||||
destroy(alloc, element);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -888,9 +907,9 @@ extern "C" {
|
||||
|
||||
void *myself = Thread::myself();
|
||||
|
||||
Lock_guard<Lock> key_list_lock_guard(key_list_lock);
|
||||
Lock_guard<Lock> key_list_lock_guard(key_list_lock());
|
||||
|
||||
for (Key_element *key_element = key_list[key].first(); key_element;
|
||||
for (Key_element *key_element = keys().key[key].first(); key_element;
|
||||
key_element = key_element->next())
|
||||
if (key_element->thread_base == myself) {
|
||||
key_element->value = value;
|
||||
@ -898,8 +917,9 @@ extern "C" {
|
||||
}
|
||||
|
||||
/* key element does not exist yet - create a new one */
|
||||
Key_element *key_element = new (object_alloc) Key_element(Thread::myself(), value);
|
||||
key_list[key].insert(key_element);
|
||||
Libc::Allocator alloc { };
|
||||
Key_element *key_element = new (alloc) Key_element(Thread::myself(), value);
|
||||
keys().key[key].insert(key_element);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -911,9 +931,9 @@ extern "C" {
|
||||
|
||||
void *myself = Thread::myself();
|
||||
|
||||
Lock_guard<Lock> key_list_lock_guard(key_list_lock);
|
||||
Lock_guard<Lock> key_list_lock_guard(key_list_lock());
|
||||
|
||||
for (Key_element *key_element = key_list[key].first(); key_element;
|
||||
for (Key_element *key_element = keys().key[key].first(); key_element;
|
||||
key_element = key_element->next())
|
||||
if (key_element->thread_base == myself)
|
||||
return (void*)(key_element->value);
|
||||
@ -929,7 +949,8 @@ extern "C" {
|
||||
return EINTR;
|
||||
|
||||
if (!once->mutex) {
|
||||
pthread_mutex_t p = new (object_alloc) pthread_mutex(0);
|
||||
Libc::Allocator alloc { };
|
||||
pthread_mutex_t p = new (alloc) pthread_mutex(0);
|
||||
/* be paranoid */
|
||||
if (!p)
|
||||
return EINTR;
|
||||
@ -948,7 +969,7 @@ extern "C" {
|
||||
* free our mutex since it is not used.
|
||||
*/
|
||||
if (p)
|
||||
destroy(object_alloc, p);
|
||||
destroy(alloc, p);
|
||||
}
|
||||
|
||||
once->mutex->lock();
|
||||
|
@ -21,37 +21,36 @@
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
static Libc::Allocator object_alloc;
|
||||
|
||||
|
||||
int Libc::pthread_create(pthread_t *thread,
|
||||
void *(*start_routine) (void *), void *arg,
|
||||
size_t stack_size, char const * name,
|
||||
Genode::Cpu_session * cpu, Genode::Affinity::Location location)
|
||||
{
|
||||
pthread_t thread_obj = new (object_alloc)
|
||||
pthread(start_routine, arg,
|
||||
stack_size, name, cpu, location);
|
||||
if (!thread_obj)
|
||||
return EAGAIN;
|
||||
Libc::Allocator alloc { };
|
||||
pthread_t thread_obj = new (alloc)
|
||||
pthread(start_routine, arg,
|
||||
stack_size, name, cpu, location);
|
||||
if (!thread_obj)
|
||||
return EAGAIN;
|
||||
|
||||
*thread = thread_obj;
|
||||
*thread = thread_obj;
|
||||
|
||||
thread_obj->start();
|
||||
thread_obj->start();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Libc::pthread_create(pthread_t *thread, Genode::Thread &t)
|
||||
{
|
||||
pthread_t thread_obj = new (object_alloc) pthread(t);
|
||||
Libc::Allocator alloc { };
|
||||
pthread_t thread_obj = new (alloc) pthread(t);
|
||||
|
||||
if (!thread_obj)
|
||||
return EAGAIN;
|
||||
if (!thread_obj)
|
||||
return EAGAIN;
|
||||
|
||||
*thread = thread_obj;
|
||||
return 0;
|
||||
*thread = thread_obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user