Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
android /platform /bionic /refs/heads/main /. /libc /bionic /pthread_atfork.cpp
blob: 0dcabdfb2de0584d98321237aab2f19a3e982da9 [file] [log] [blame] [edit]
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include<errno.h>
#include<pthread.h>
#include<stdlib.h>
#include"platform/bionic/macros.h"
structatfork_t{
atfork_t* next;
atfork_t* prev;
void(*prepare)(void);
void(*child)(void);
void(*parent)(void);
void* dso_handle;
};
classatfork_list_t{
public:
constexpratfork_list_t(): first_(nullptr), last_(nullptr){}
template<typename F>
void walk_forward(F f){
for(atfork_t* it= first_; it!=nullptr; it= it->next){
f(it);
}
}
template<typename F>
void walk_backwards(F f){
for(atfork_t* it= last_; it!=nullptr; it= it->prev){
f(it);
}
}
void push_back(atfork_t* entry){
entry->next=nullptr;
entry->prev= last_;
if(entry->prev!=nullptr){
entry->prev->next= entry;
}
if(first_==nullptr){
first_= entry;
}
last_= entry;
}
template<typename F>
void remove_if(F predicate){
atfork_t* it= first_;
while(it!=nullptr){
if(predicate(it)){
atfork_t* entry= it;
it= it->next;
remove(entry);
}else{
it= it->next;
}
}
}
private:
void remove(atfork_t* entry){
if(entry->prev!=nullptr){
entry->prev->next= entry->next;
}else{
first_= entry->next;
}
if(entry->next!=nullptr){
entry->next->prev= entry->prev;
}else{
last_= entry->prev;
}
free(entry);
}
atfork_t* first_;
atfork_t* last_;
BIONIC_DISALLOW_COPY_AND_ASSIGN(atfork_list_t);
};
staticpthread_mutex_t g_atfork_list_mutex= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
staticatfork_list_t g_atfork_list;
void __bionic_atfork_run_prepare(){
// We lock the atfork list here, unlock it in the parent, and reset it in the child.
// This ensures that nobody can modify the handler array between the calls
// to the prepare and parent/child handlers.
pthread_mutex_lock(&g_atfork_list_mutex);
// Call pthread_atfork() prepare handlers. POSIX states that the prepare
// handlers should be called in the reverse order of the parent/child
// handlers, so we iterate backwards.
g_atfork_list.walk_backwards([](atfork_t* it){
if(it->prepare!=nullptr){
it->prepare();
}
});
}
void __bionic_atfork_run_child(){
g_atfork_list_mutex= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutex_lock(&g_atfork_list_mutex);
g_atfork_list.walk_forward([](atfork_t* it){
if(it->child!=nullptr){
it->child();
}
});
pthread_mutex_unlock(&g_atfork_list_mutex);
}
void __bionic_atfork_run_parent(){
g_atfork_list.walk_forward([](atfork_t* it){
if(it->parent!=nullptr){
it->parent();
}
});
pthread_mutex_unlock(&g_atfork_list_mutex);
}
// __register_atfork is the name used by glibc
extern"C"int __register_atfork(void(*prepare)(void),void(*parent)(void),
void(*child)(void),void* dso){
atfork_t* entry=reinterpret_cast<atfork_t*>(malloc(sizeof(atfork_t)));
if(entry==nullptr){
return ENOMEM;
}
entry->prepare= prepare;
entry->parent= parent;
entry->child= child;
entry->dso_handle= dso;
pthread_mutex_lock(&g_atfork_list_mutex);
g_atfork_list.push_back(entry);
pthread_mutex_unlock(&g_atfork_list_mutex);
return0;
}
extern"C" __LIBC_HIDDEN__void __unregister_atfork(void* dso){
pthread_mutex_lock(&g_atfork_list_mutex);
g_atfork_list.remove_if([&](constatfork_t* entry){
return entry->dso_handle== dso;
});
pthread_mutex_unlock(&g_atfork_list_mutex);
}

[8]ページ先頭

©2009-2025 Movatter.jp