Make more threading improvements

- ASAN memory morgue is now lockless
- Make C11 atomics header more portable
- Rewrote pthread keys support to be lockless
- Simplify Python's unicode table unpacking code
- Make crash report write(2) closer to being atomic
- Make it possible to strace/ftrace a single thread
- ASAN now checks nul-terminated strings fast and properly
- Windows fork() now restores TLS memory of calling thread
This commit is contained in:
Justine Tunney 2022-11-01 22:36:03 -07:00
parent d7b88734cd
commit e522aa3a07
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
189 changed files with 1363 additions and 1217 deletions

View file

@ -17,13 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/errno.h"
#include "libc/intrin/kmalloc.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/str/str.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
static struct AtForks {
pthread_mutex_t lock;
pthread_spinlock_t lock;
struct AtFork {
struct AtFork *p[2];
atfork_f f[3];
@ -34,12 +37,12 @@ static void _pthread_onfork(int i) {
struct AtFork *a;
struct PosixThread *pt;
_unassert(0 <= i && i <= 2);
if (!i) pthread_mutex_lock(&_atforks.lock);
if (!i) pthread_spin_lock(&_atforks.lock);
for (a = _atforks.list; a; a = a->p[!i]) {
if (a->f[i]) a->f[i]();
_atforks.list = a;
}
if (i) pthread_mutex_unlock(&_atforks.lock);
if (i) pthread_spin_unlock(&_atforks.lock);
if (i == 2) {
_pthread_zombies_purge();
if (__tls_enabled) {
@ -51,29 +54,36 @@ static void _pthread_onfork(int i) {
void _pthread_onfork_prepare(void) {
_pthread_onfork(0);
__kmalloc_lock();
__mmi_lock();
}
void _pthread_onfork_parent(void) {
__mmi_unlock();
__kmalloc_unlock();
_pthread_onfork(1);
}
void _pthread_onfork_child(void) {
extern pthread_mutex_t __mmi_lock_obj;
bzero(&__mmi_lock_obj, sizeof(__mmi_lock_obj));
__kmalloc_unlock();
_pthread_onfork(2);
}
int _pthread_atfork(atfork_f prepare, atfork_f parent, atfork_f child) {
int rc;
struct AtFork *a;
a = kmalloc(sizeof(struct AtFork));
if (!(a = kmalloc(sizeof(struct AtFork)))) return ENOMEM;
a->f[0] = prepare;
a->f[1] = parent;
a->f[2] = child;
pthread_mutex_lock(&_atforks.lock);
pthread_spin_lock(&_atforks.lock);
a->p[0] = 0;
a->p[1] = _atforks.list;
if (_atforks.list) _atforks.list->p[0] = a;
_atforks.list = a;
pthread_mutex_unlock(&_atforks.lock);
pthread_spin_unlock(&_atforks.lock);
rc = 0;
return rc;
}