mirror of
https://github.com/HeyPuter/gex.git
synced 2026-11-13 20:12:43 -10:00
The fetch already worked; what did not was what apt does with it.
E: Dynamic MMap ran out of room. Please increase the size of
APT::Cache-Start. Current value: 28311552.
E: Problem with MergeList .../binary-arm64_Packages
Bookworm's arm64 index is 49 MB of Packages and 32 MB of Translation-en, and
apt builds its cache in one mapping that it grows as it parses. Started at
the default it reaches about 27 MB and gives up. The size is a decision, not
a defect, so it is a decision the image makes: `/etc/apt/apt.conf.d/99gex`
sets `APT::Cache-Start` to 128 MB, next to the other four lines that already
tell apt it is running somewhere unusual. With that in the rootfs and nothing
on the command line:
== apt-get update ==
Get:1 http://deb.debian.org/debian bookworm InRelease [151 kB]
Get:2 http://deb.debian.org/debian bookworm/main arm64 Packages [8689 kB]
Get:3 http://deb.debian.org/debian bookworm/main Translation-en [6107 kB]
Fetched 14.9 MB in 3min 39s
Reading package lists...
== apt exit 0 ==
-rw-r--r-- 49434864 deb.debian.org_debian_dists_bookworm_main_binary-arm64_Packages
-rw-r--r-- 32699363 deb.debian.org_debian_dists_bookworm_main_i18n_Translation-en
and `apt-cache show bash` answers out of it.
Threads as Workers, continued, and still not working. Four more things that
were one set of bytes for a whole process and have to be one per Worker:
which thread it is running, where it resumes, why it stopped, and whether it
meant to give the stack back -- the last of those is why a thread that handed
the stack back correctly was reported as having crashed inside the shim. A
thread also has to be *entered* on its own registers, which it was not: `run`
starts at the first thread's context, so four threads all entered at 0x1000,
re-executed whatever the main thread was in the middle of, and one of them
came out the other side having forked. And a Worker that owns one thread must
not switch: neither the scheduler nor the safepoint may hand it another
thread, however ready that thread looks.
Where it stands: four threads start in four Workers, run their own registers,
and then one branches to address zero out of a futex. What is left is the
same kind of thing again -- the kernel keeps "which context is running" in a
field, and a field is per process.
`tests/integration/programs/thread-parallel.c` is the small version of
`threads.c`: four threads that share nothing, so that when both fail it says
whether the mechanism is broken or only the contention is.
53 lines
1.6 KiB
C
53 lines
1.6 KiB
C
/* Threads that do not fight over anything.
|
|
*
|
|
* The smallest program that can tell whether a thread ran at all in a Worker
|
|
* of its own: each one writes only its own slot, and the main thread joins
|
|
* them and adds up. No mutex, no condition variable, one futex per join.
|
|
*
|
|
* `threads.c` next door is the hard version and shares a mutex twenty
|
|
* thousand times per thread. When both fail, this one says whether the
|
|
* mechanism is broken or only the contention is, and those are days apart.
|
|
*/
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
|
|
#define N 4
|
|
#define ITERS 100000
|
|
|
|
struct arg { int id; long sum; int tid_seen; };
|
|
static __thread int mine;
|
|
|
|
static void *worker(void *p) {
|
|
struct arg *a = p;
|
|
/* Thread-local storage, which is the one piece of per-thread state that
|
|
is not registers: each thread must see only its own. */
|
|
mine = a->id;
|
|
for (int i = 0; i < ITERS; i++) a->sum += i;
|
|
a->tid_seen = mine;
|
|
return NULL;
|
|
}
|
|
|
|
int main(void) {
|
|
pthread_t t[N];
|
|
struct arg args[N];
|
|
for (int i = 0; i < N; i++) {
|
|
args[i] = (struct arg){.id = i + 1, .sum = 0, .tid_seen = -1};
|
|
if (pthread_create(&t[i], NULL, worker, &args[i]) != 0) {
|
|
printf("pthread_create failed\n");
|
|
return 1;
|
|
}
|
|
}
|
|
long total = 0;
|
|
int tls_ok = 1;
|
|
for (int i = 0; i < N; i++) {
|
|
pthread_join(t[i], NULL);
|
|
total += args[i].sum;
|
|
if (args[i].tid_seen != i + 1) tls_ok = 0;
|
|
}
|
|
printf("sum %ld expected %ld\n", total, (long)N * ITERS * (ITERS - 1) / 2);
|
|
printf("tls %s\n", tls_ok ? "ok" : "WRONG");
|
|
printf("main tls %d\n", mine);
|
|
printf("done\n");
|
|
return 0;
|
|
}
|