Import LinuxCNC source tree

This commit is contained in:
Wang Dequan
2026-08-20 06:17:39 +08:00
commit 2c814634c3
9429 changed files with 10556013 additions and 0 deletions

View File

@@ -0,0 +1 @@
test passed

View File

@@ -0,0 +1,112 @@
/*
* Concurrency / correctness test for the emcmotError MPSC ring buffer.
*
* Spawns NPROD producer threads pumping NMSG messages each, plus one
* consumer that drains. Verifies every message arrives exactly once
* and that messages from each individual producer arrive in producer-
* local sequence order. Across producers any interleaving is allowed.
*/
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <emcmotcfg.h>
#include "motion.h"
#include "dbuf.h"
#include "stashf.h"
#include <rtapi_atomic.h>
#define NPROD 8
#define NMSG 100000
static emcmot_error_t errlog;
static rtapi_atomic_int producers_done = 0;
static void *producer_fn(void *arg) {
long id = (long)arg;
char buf[64];
for (int i = 0; i < NMSG; i++) {
snprintf(buf, sizeof(buf), "P%ld:%010d", id, i);
while (emcmotErrorPut(&errlog, buf) < 0) {
sched_yield();
}
}
atomic_fetch_add(&producers_done, 1);
return NULL;
}
static void *consumer_fn(void *arg) {
(void)arg;
long total = (long)NPROD * NMSG;
long received = 0;
int per_producer[NPROD] = {0};
char raw[EMCMOT_ERROR_LEN];
char msg[EMCMOT_ERROR_LEN];
int errors = 0;
while (received < total) {
struct dbuf d;
struct dbuf_iter di;
/* dbuf_init zero-fills the buffer, so call it BEFORE
emcmotErrorGet, which then writes the received bytes in. */
dbuf_init(&d, (unsigned char *)raw, EMCMOT_ERROR_LEN);
if (emcmotErrorGet(&errlog, raw) == 0) {
dbuf_iter_init(&di, &d);
if (snprintdbuf(msg, sizeof(msg), &di) < 0) {
fprintf(stderr, "snprintdbuf failed\n");
errors++;
received++;
continue;
}
long pid;
int seq;
if (sscanf(msg, "P%ld:%d", &pid, &seq) != 2
|| pid < 0 || pid >= NPROD) {
fprintf(stderr, "bad msg: '%s'\n", msg);
errors++;
} else if (seq != per_producer[pid]) {
fprintf(stderr, "out-of-order P%ld: got %d, want %d\n",
pid, seq, per_producer[pid]);
errors++;
} else {
per_producer[pid]++;
}
received++;
} else {
if (atomic_load(&producers_done) >= NPROD) {
struct timespec ts = {0, 1000000};
nanosleep(&ts, NULL);
} else {
sched_yield();
}
}
}
if (errors == 0) {
printf("test passed\n");
} else {
printf("test FAILED with %d errors\n", errors);
}
return errors == 0 ? (void *)0 : (void *)1;
}
int main(void) {
emcmotErrorInit(&errlog);
pthread_t prods[NPROD];
pthread_t cons;
pthread_create(&cons, NULL, consumer_fn, NULL);
for (long i = 0; i < NPROD; i++) {
pthread_create(&prods[i], NULL, producer_fn, (void *)i);
}
for (long i = 0; i < NPROD; i++) {
pthread_join(prods[i], NULL);
}
void *cret;
pthread_join(cons, &cret);
return cret ? 1 : 0;
}

View File

@@ -0,0 +1,27 @@
#!/bin/sh
# Concurrency / correctness test for the emcmotError MPSC ring buffer.
# RIP-only: builds the test driver against the in-tree motion sources.
SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)"
TOPDIR="$(cd "$SCRIPTDIR/../../.." && pwd)"
SRCDIR="${TOPDIR}/src/emc/motion"
INCDIR="${TOPDIR}/include"
if [ ! -f "${SRCDIR}/emcmotutil.c" ]; then
echo "skip: motion sources not found (RIP build required)"
exit 0
fi
gcc -O -pthread -DULAPI -Wall \
-I"${INCDIR}" \
-I"${SRCDIR}" \
"${SCRIPTDIR}/test.c" \
"${SRCDIR}/emcmotutil.c" \
"${SRCDIR}/dbuf.c" \
"${SRCDIR}/stashf.c" \
-o "${SCRIPTDIR}/test" || { echo "compile failed"; exit 1; }
"${SCRIPTDIR}/test"
exitval=$?
rm -f "${SCRIPTDIR}/test"
exit $exitval

View File

@@ -0,0 +1,2 @@
count=200000
test passed

View File

@@ -0,0 +1,38 @@
#include <rtapi_mutex.h>
#include <pthread.h>
#include <assert.h>
#include <stdio.h>
// to make this test fail, you can...
#if 0
#define rtapi_mutex_give(x) (void)0
#define rtapi_mutex_get(x) (void)0
#endif
const unsigned int N = 100000;
unsigned long mut;
unsigned long count;
void *thread_fun(void *unused) {
for(unsigned long i=0; i<N; i++) {
rtapi_mutex_get(&mut);
unsigned long tmp = count;
tmp++;
sched_yield();
count = tmp;
rtapi_mutex_give(&mut);
}
return unused;
}
int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, thread_fun, NULL);
pthread_create(&t2, NULL, thread_fun, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("count=%lu\n", count);
assert(count == 2*N);
printf("test passed\n");
return 0;
}

5
tests/lowlevel/mutex/test.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
gcc -O -I"${HEADERS}" test.c -o test -DULAPI -std=gnu99 -pthread || exit 1
./test; exitval=$?
rm -f test
exit $exitval