Skip to content

Commit 6a67088

Browse files
committed
Fix tfork() when compiled without optimizations
1 parent c54da20 commit 6a67088

File tree

1 file changed

+48
-29
lines changed

1 file changed

+48
-29
lines changed

mintlib/thread.c

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include <support.h>
2525
#include "lib.h"
2626

27-
#define SIZE 4096L
27+
#define THREAD_STACKSIZE 4096L
2828

2929

3030
/* this is used by wait() and wait3() to retrieve the child's exit code */
@@ -33,52 +33,66 @@ long __waitval = -ENOENT;
3333
/* and this is used to retrieve the child's time */
3434
long __waittime = 0;
3535

36-
static void __CDECL
37-
startup(register BASEPAGE *b)
36+
/*
37+
* This function must not be compiled without optimization,
38+
* because we change the stack, and the BASEPAGE parameter
39+
* is not accessible afterwards.
40+
*/
41+
#pragma GCC optimize "-Os"
42+
#pragma GCC optimize "-fomit-frame-pointer"
43+
44+
static void __CDECL startup(BASEPAGE *b)
3845
{
39-
register int (*func)(long);
40-
register long arg;
41-
_setstack(((char *)b) + SIZE);
46+
int (*func)(long);
47+
long arg;
48+
BASEPAGE *parent;
49+
50+
parent = b->p_parent;
51+
_setstack(b->p_hitpa);
4252
func = (int (*)(long))b->p_dbase;
4353
arg = b->p_dlen;
4454

4555
/* If this is a thread, it doesn't need
4656
* own copy of the environment, right?
4757
*/
4858
Mfree(b->p_env);
49-
b->p_env = _base->p_env;
59+
b->p_env = parent->p_env;
5060

5161
/* copy from parents basepage for debuggers... */
52-
b->p_tbase = _base->p_tbase;
53-
b->p_tlen = _base->p_tlen;
54-
b->p_dbase = _base->p_dbase;
55-
b->p_dlen = _base->p_dlen;
56-
b->p_bbase = _base->p_bbase;
57-
b->p_blen = _base->p_blen;
62+
b->p_tbase = parent->p_tbase;
63+
b->p_tlen = parent->p_tlen;
64+
b->p_dbase = parent->p_dbase;
65+
b->p_dlen = parent->p_dlen;
66+
b->p_bbase = parent->p_bbase;
67+
b->p_blen = parent->p_blen;
5868

5969
Pterm((*func)(arg));
70+
__builtin_unreachable();
6071
}
6172

6273
/* use long instead of int so vfork works OK with -mshort */
6374
long
6475
tfork(int (*func)(long), long arg)
6576
{
66-
register BASEPAGE *b;
67-
register long pid;
68-
register long savpending, savmask;
69-
register BASEPAGE *savbase;
77+
BASEPAGE *b;
78+
long pid;
79+
long savpending, savmask;
7080
sighandler_t savhandler[NSIG];
7181
long now;
7282
int i;
83+
long stacksize = THREAD_STACKSIZE;
7384

7485
b = (BASEPAGE *)Pexec(PE_CBASEPAGE, 0L, "", 0L);
75-
(void)Mshrink(b, SIZE+256);
86+
if ((long)b <= 0)
87+
return (long)b;
88+
(void)Mshrink(b, stacksize + sizeof(*b));
7689
b->p_tbase = (char *)startup;
7790
b->p_dbase = (char *)func;
7891
b->p_dlen = arg;
79-
b->p_hitpa = ((char *)b) + SIZE + 256;
80-
81-
pid = Pexec(104, 0L, b, 0L);
92+
b->p_blen = stacksize;
93+
b->p_hitpa = ((char *)b) + stacksize + sizeof(*b);
94+
95+
pid = Pexec(PE_ASYNC_GO, 0L, b, 0L);
8296
if (pid == -ENOSYS)
8397
{
8498
/* save the signal masks and signal handlers,
@@ -90,30 +104,35 @@ tfork(int (*func)(long), long arg)
90104
_sigmask = 0;
91105
for (i = 0; i < NSIG; i++)
92106
savhandler[i] = _sig_handler[i];
93-
savbase = _base;
94-
_base = b;
95107

96108
now = _clock();
97-
pid = Pexec(4, 0L, b, 0L);
109+
pid = Pexec(PE_GO, 0L, b, 0L);
98110

99-
_base = savbase;
100111
/* restore signal stuff */
101112
for (i = 0; i < NSIG; i++)
102113
_sig_handler[i] = savhandler[i];
103114
_sigmask = savmask;
104115
_sigpending = savpending;
105-
if (pid >= 0) {
116+
if (pid >= 0)
117+
{
106118
long retval = pid;
107119

108-
/* see the TOS algorithm for getpid() */
120+
/* see the TOS algorithm for getpid() */
109121
pid = ((long)b) >> 8;
110122
__waitval = (pid << 16) | retval;
111123
raise(SIGCHLD);
112124
__waittime = _clock() - now;
113125
_childtime += __waittime;
126+
/* child already terminated, but memory of basepage & env is still owned by us */
127+
(void)Mfree(b->p_env); /* free the memory */
128+
(void)Mfree(b);
114129
}
115130
}
116-
(void)Mfree(b->p_env); /* free the memory */
117-
(void)Mfree(b);
131+
if (pid < 0)
132+
{
133+
(void)Mfree(b->p_env); /* free the memory */
134+
(void)Mfree(b);
135+
}
136+
/* memory of basepage & env is now owned by child */
118137
return pid;
119138
}

0 commit comments

Comments
 (0)