79 lines
2.2 KiB
C
79 lines
2.2 KiB
C
// Stress concurrent malloc/free (fix: the __heapLock semaphore mutex). The
|
|
// parent and a forked child both hammer the SHARED heap -- each repeatedly
|
|
// malloc()s a block, fills it with a thread-unique pattern, holds it briefly (to
|
|
// invite preemption), verifies the pattern survived, and free()s it. If the
|
|
// free-list critical section were not serialized, the two threads' interleaved
|
|
// malloc/free could hand the same block to both (or corrupt the list), so a
|
|
// pattern check would fail or the walk would crash. Both loops completing with
|
|
// intact patterns shows the heap is concurrency-safe.
|
|
//
|
|
// 0x025082 AAAA parent's alloc loop finished with every pattern intact
|
|
// 0x025084 CCCC child's alloc loop finished with every pattern intact
|
|
// 0x025086 E0DD parent reaped the child
|
|
#include <stdint.h>
|
|
|
|
extern int fork(void *subr);
|
|
extern int wait(int *status);
|
|
extern __attribute__((noreturn)) void _exit(int status);
|
|
extern void *malloc(unsigned long n);
|
|
extern void free(void *p);
|
|
|
|
#define M(a) (*(volatile uint16_t *)(a))
|
|
#define ITERS 120
|
|
|
|
|
|
static uint16_t allocLoop(uint16_t tag) {
|
|
volatile uint16_t *p;
|
|
uint16_t ok;
|
|
int i;
|
|
int j;
|
|
|
|
ok = 1;
|
|
for (i = 0; i < ITERS; i++) {
|
|
p = (volatile uint16_t *)malloc(32);
|
|
if (p == 0) {
|
|
ok = 0;
|
|
break;
|
|
}
|
|
for (j = 0; j < 16; j++) {
|
|
p[j] = (uint16_t)(tag + j);
|
|
}
|
|
for (volatile int s = 0; s < 40; s++) { // hold the block; invite a task swap
|
|
}
|
|
for (j = 0; j < 16; j++) {
|
|
if (p[j] != (uint16_t)(tag + j)) {
|
|
ok = 0;
|
|
}
|
|
}
|
|
free((void *)p);
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
|
|
static void child(void) {
|
|
uint16_t ok;
|
|
ok = allocLoop(0xC000);
|
|
M(0x025084UL) = ok ? 0xCCCC : 0xDEAD;
|
|
_exit(0);
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
uint16_t ok;
|
|
int st;
|
|
|
|
M(0x025082UL) = 0xDEAD;
|
|
M(0x025084UL) = 0xDEAD;
|
|
M(0x025086UL) = 0xDEAD;
|
|
|
|
fork((void *)child);
|
|
ok = allocLoop(0xA000); // parent hammers the heap concurrently
|
|
M(0x025082UL) = ok ? 0xAAAA : 0xDEAD;
|
|
|
|
wait(&st);
|
|
M(0x025086UL) = 0xE0DD;
|
|
for (volatile unsigned long j = 0; j < 300000UL; j++) {
|
|
}
|
|
return 0;
|
|
}
|