xref: /aosp_15_r20/external/musl/src/thread/pthread_atfork.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1 #include <pthread.h>
2 #include <errno.h>
3 #include "libc.h"
4 #include "lock.h"
5 
6 #define malloc __libc_malloc
7 #define calloc undef
8 #define realloc undef
9 #define free undef
10 
11 static struct atfork_funcs {
12 	void (*prepare)(void);
13 	void (*parent)(void);
14 	void (*child)(void);
15 	struct atfork_funcs *prev, *next;
16 } *funcs;
17 
18 static volatile int lock[1];
19 
__fork_handler(int who)20 void __fork_handler(int who)
21 {
22 	struct atfork_funcs *p;
23 	if (!funcs) return;
24 	if (who < 0) {
25 		LOCK(lock);
26 		for (p=funcs; p; p = p->next) {
27 			if (p->prepare) p->prepare();
28 			funcs = p;
29 		}
30 	} else {
31 		for (p=funcs; p; p = p->prev) {
32 			if (!who && p->parent) p->parent();
33 			else if (who && p->child) p->child();
34 			funcs = p;
35 		}
36 		UNLOCK(lock);
37 	}
38 }
39 
pthread_atfork(void (* prepare)(void),void (* parent)(void),void (* child)(void))40 int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
41 {
42 	struct atfork_funcs *new = malloc(sizeof *new);
43 	if (!new) return ENOMEM;
44 
45 	LOCK(lock);
46 	new->next = funcs;
47 	new->prev = 0;
48 	new->prepare = prepare;
49 	new->parent = parent;
50 	new->child = child;
51 	if (funcs) funcs->prev = new;
52 	funcs = new;
53 	UNLOCK(lock);
54 	return 0;
55 }
56