aboutsummaryrefslogtreecommitdiff
path: root/arm-probe
diff options
context:
space:
mode:
authorAndy Green <andy.green@linaro.org>2012-10-11 17:47:29 +0800
committerAndy Green <andy.green@linaro.org>2012-10-11 17:47:29 +0800
commit020f93df6d6354a18e05a65707967ce53bba26e5 (patch)
treefab16c80d0ec12e8c330454bcb72738667d747bf /arm-probe
parent813f8f29a4f3322d2fc97ecf17c443e5ba66c29a (diff)
issue libarmep results using shared mem from forked process
This decouples the AEP service and correction / trigger process from the process that does something with the results. This allows an SMP box to dedicate one core just for AEP service, with the other cores free for whatever you're doing with the output. This allows scrolling of stdout for 9 channels without causing AEP service underflow on this laptop now. The callback is also removed and the arm-probe code further simplified with more handled in the library. Signed-off-by: Andy Green <andy.green@linaro.org>
Diffstat (limited to 'arm-probe')
-rw-r--r--arm-probe/Makefile.am4
-rw-r--r--arm-probe/arm-probe.c295
2 files changed, 103 insertions, 196 deletions
diff --git a/arm-probe/Makefile.am b/arm-probe/Makefile.am
index 426ff71..1671740 100644
--- a/arm-probe/Makefile.am
+++ b/arm-probe/Makefile.am
@@ -1,6 +1,6 @@
bin_PROGRAMS=arm-probe
arm_probe_SOURCES=arm-probe.c
-arm_probe_CFLAGS=-fPIC -Wall -std=gnu99 -pedantic
-arm_probe_LDFLAGS=-fPIC
+arm_probe_CFLAGS=-fPIC -Wall -Werror -std=gnu99 -pedantic -pthread
+arm_probe_LDFLAGS=-fPIC -pthread
arm_probe_LDADD=-L../libarmep -larmep
diff --git a/arm-probe/arm-probe.c b/arm-probe/arm-probe.c
index 8c4077d..0b8453c 100644
--- a/arm-probe/arm-probe.c
+++ b/arm-probe/arm-probe.c
@@ -27,14 +27,8 @@ char stdinbuf[512];
char stdinline[512] = "";
int stdinpos = 0;
int stdinlen = 0;
-double do_average = 0;
-
-static void issue_samples(enum samples_actions sa, struct aep_channel *ch,
- double voltage, double current);
-
struct aep_context aep_context = {
- .samples = issue_samples,
.config_filepath = "./config",
.highest = -1,
.decimate = 1,
@@ -79,139 +73,8 @@ int get_stdin_line(char *buf, int maxlen)
}
}
return -1;
-}
-
-void add_pollfd(struct aep_context *aep_context, int fd, int events)
-{
- aep_context->pollfds[aep_context->count_pollfds].fd = fd;
- aep_context->pollfds[aep_context->count_pollfds].events = events;
- aep_context->pollfds[aep_context->count_pollfds++].revents = 0;
-}
-
-void remove_pollfd(struct aep_context *aep_context, int fd)
-{
- int n;
-
- for (n = 0; n < aep_context->count_pollfds; n++)
- if (aep_context->pollfds[n].fd == fd) {
- while (n < aep_context->count_pollfds) {
- aep_context->pollfds[n] = aep_context->pollfds[n + 1];
- n++;
- }
- aep_context->count_pollfds--;
- }
-}
-
-
-/*
- * this is the callback where the results appear
- */
-
-static void issue_samples(enum samples_actions sa, struct aep_channel *ch,
- double voltage, double current)
-{
- static int periodic;
- static char titles[4096];
- static int pos;
-
- switch (sa) {
-
- case AEPSA_ADD_POLLFD:
- add_pollfd(&aep_context, (int)voltage, (int)current);
- break;
-
- case AEPSA_REMOVE_POLLFD:
- remove_pollfd(&aep_context, (int)voltage);
- break;
-
- case AEPSA_DATA_STARTING:
- printf("#\n");
- pos = 0;
- if (!stdinline[0])
- break;
- printf("%s", stdinline);
- get_stdin_line(stdinline, sizeof stdinline);
-
- break;
- case AEPSA_DATA_STARTING_CHANNELS:
-
- printf("# %s\t%s\t%s\t%s\n",
- ch->channel_name, ch->channel_name_pretty, ch->supply, ch->colour);
-
- if (just_power)
- pos += sprintf(&titles[pos], " %s(W)",
- ch->channel_name_pretty);
- else
- pos += sprintf(&titles[pos]," %s(V) %s(A) %s(W)",
- ch->channel_name_pretty,
- ch->channel_name_pretty,
- ch->channel_name_pretty);
- break;
-
- case AEPSA_DATA_STARTING_DONE:
- printf("#\nsample");
- puts(titles);
- break;
-
- case AEPSA_START_PRE:
- periodic++;
- if (periodic & 0x1ff)
- break;
- fprintf(stderr, "ARMED ");
- break;
- case AEPSA_SAMPLE_PRE:
- if (periodic & 0x1ff)
- break;
- if (just_power)
- fprintf(stderr, " %.5f", voltage * current);
- else
- fprintf(stderr, " %.2f %.4f %.5f",
- voltage, current, voltage * current);
- break;
- case AEPSA_END_PRE:
- if (periodic & 0x1ff)
- break;
- fprintf(stderr, "\n");
- break;
-
- case AEPSA_START:
- periodic++;
- if (stdinline[0]) {
- printf("%s", stdinline);
- if (get_stdin_line(stdinline, sizeof stdinline))
- stdinline[0] = '\0';
- } else
- printf("%f", voltage);
- if (periodic & 0x1ff)
- break;
- fprintf(stderr, "TRIGD ");
- break;
- case AEPSA_SAMPLE:
- if (just_power)
- printf(" %.5f", voltage * current);
- else
- printf(" %.2f %.4f %.5f",
- voltage, current, voltage * current);
- if (periodic & 0x1ff)
- break;
- if (just_power)
- fprintf(stderr, " %.5f", voltage * current);
- else
- fprintf(stderr, " %.2f %.4f %.5f",
- voltage, current, voltage * current);
- break;
- case AEPSA_END:
- printf("\n");
- if (periodic & 0x1ff)
- break;
- fprintf(stderr, "\n");
- break;
- }
}
-
-
-
static struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
@@ -249,10 +112,11 @@ int main(int argc, char *argv[])
char hostname[200];
char date[200];
int n = 0;
- struct aep_channel *ch;
+ int m, i;
+ int periodic = 0;
double tt;
- int m;
- int i;
+ struct aep_result *aep_result;
+ int first = 1;
loop = 1;
@@ -265,7 +129,7 @@ int main(int argc, char *argv[])
continue;
switch (n) {
case 'a':
- do_average = atof(optarg);
+ aep_context.do_average = atof(optarg);
break;
case 'z':
fprintf(stderr, "\n\n *** Note: for autozero, you "
@@ -415,6 +279,17 @@ int main(int argc, char *argv[])
}
configure(&aep_context, NULL, "xx", aep_context.config_filepath, NULL);
+
+ /*
+ * fork off the AEP service process
+ * runs in its own process to exploit SMP to dedicate one core for that
+ * what happens to samples is decoupled from capture process with large
+ * shared-memory buffer to allow for jitter
+ */
+
+ if (aep_init_and_fork(&aep_context) < 1)
+ return 0; /* child process exit */
+
printf("# configuration: %s\n", aep_context.config_filepath);
printf("# config_name: %s\n", aep_context.configuration_name);
@@ -438,37 +313,86 @@ int main(int argc, char *argv[])
printf("#\n");
/*
- * the main service loop
+ * service any AEP results
*/
- aep_context.poll_timeout_ms = 10;
- init_interpolation();
-
while (loop) {
- n = poll(aep_context.pollfds, aep_context.count_pollfds, aep_context.poll_timeout_ms);
- if (n < 0)
- loop = 0;
+ aep_result = aep_wait_for_next_result(&aep_context);
+ if (!aep_result) {
+ if (aep_context.aep_shared->finished)
+ loop = 0;
- for (n = 0; n < aep_context.count_pollfds; n++)
- if (aep_context.pollfds[n].revents)
- if (service_aeps(&aep_context, aep_context.pollfds[n].fd) < 0)
- loop = 0;
+ continue;
+ }
- if (service_aeps(&aep_context, -1) < 0)
- loop = 0;
+ if (first) {
+ first = 0;
+ for (n = 0; n < aep_context.aep_shared->chans; n++)
+ printf("# %s\t%s\t%s\t%s\n",
+ aep_context.aep_shared->channel_name[n],
+ aep_context.aep_shared->channel_name_pretty[n],
+ aep_context.aep_shared->supply[n],
+ aep_context.aep_shared->colour[n]);
+
+ printf("#\n#\ntime ");
+ for (n = 0; n < aep_context.aep_shared->chans; n++)
+ if (just_power)
+ printf(" %s(W)", aep_context.aep_shared->channel_name_pretty[n]);
+ else
+ printf(" %s(V) %s(A) %s(W)",
+ aep_context.aep_shared->channel_name_pretty[n],
+ aep_context.aep_shared->channel_name_pretty[n],
+ aep_context.aep_shared->channel_name_pretty[n]);
+ printf("\n");
+ }
+
+ periodic++;
+ if ((periodic & 0x1ff) == 0) {
+ if (aep_result->triggered)
+ fprintf(stderr, "TRIGD ");
+ else
+ fprintf(stderr, "ARMED ");
+ }
+ if (aep_result->triggered)
+ printf("%f ", aep_result->samtime);
+ for (i = 0; i < aep_result->chans * 2; i += 2) {
+ if (aep_result->triggered) {
+ if (just_power)
+ printf(" %.5f", aep_result->buf[i] * aep_result->buf[i + 1]);
+ else
+ printf(" %.2f %.4f %.5f",
+ aep_result->buf[i], aep_result->buf[i + 1], aep_result->buf[i] * aep_result->buf[i + 1]);
+ }
+ if (periodic & 0x1ff)
+ continue;
+ if (just_power)
+ fprintf(stderr, " %.5f", aep_result->buf[i] * aep_result->buf[i + 1]);
+ else
+ fprintf(stderr, " %.2f %.4f %.5f",
+ aep_result->buf[i], aep_result->buf[i + 1], aep_result->buf[i] * aep_result->buf[i + 1]);
+ }
+ if (aep_result->triggered)
+ printf("\n");
+
+ aep_free_result(&aep_context);
+
+ if (periodic & 0x1ff)
+ continue;
+ fprintf(stderr, "\n");
}
+ aep_context.aep_shared->finished = 1;
+
/*
* we are finished if we reach here...
* append simple average to results if requested
*/
- if (aep_context.awaiting_capture == 0 &&
- aep_context.exit_after_capture && do_average) {
+ if (aep_context.do_average) {
- tt = do_average;
+ tt = aep_context.do_average;
for (m = 0; m < 2; m++) {
@@ -479,21 +403,18 @@ int main(int argc, char *argv[])
} else
printf("%f", tt);
- for (n = 0; n <= aep_context.highest; n++) {
- for (i = 0; i < CHANNELS_PER_PROBE; i++) {
- ch = &aep_context.aeps[n].ch[i];
- if (just_power)
- printf(" %.5f", ch->simple_avg[2] / ch->avg_count);
- else
- printf(" %.2f %.4f %.5f",
- ch->simple_avg[0] / ch->avg_count,
- ch->simple_avg[1] / ch->avg_count,
- ch->simple_avg[2] / ch->avg_count);
- }
+ for (n = 0; n <= aep_context.aep_shared->chans; n++) {
+ if (just_power)
+ printf(" %.5f", aep_context.aep_shared->averages[n][2]);
+ else
+ printf(" %.2f %.4f %.5f",
+ aep_context.aep_shared->averages[n][0],
+ aep_context.aep_shared->averages[n][1],
+ aep_context.aep_shared->averages[n][2]);
}
printf("\n");
- tt += do_average / 3;
+ tt += aep_context.do_average / 3;
}
}
@@ -503,36 +424,22 @@ int main(int argc, char *argv[])
fprintf(stderr, "\n\n");
- for (m = 0; m <= aep_context.highest; m++) {
- int i;
+ for (n = 0; n < aep_context.aep_shared->chans; n++) {
- if (aep_context.aeps[m].fd <= 0)
+ if (aep_context.aep_shared->min[n][0] == 999)
continue;
-
- for (i = 0; i < CHANNELS_PER_PROBE; i++) {
- ch = &aep_context.aeps[m].ch[i];
- if (configure(&aep_context, &aep_context.aeps[m],
- aep_context.aeps[m].dev_filepath,
- aep_context.config_filepath, ch) < 0)
- fprintf(stderr, "failed to update config\n");
-
- if (ch->min[0] == 999)
- continue;
-
- fprintf(stderr, "%12s: %4.2fV < %4.3fVavg < %4.2fV, "
- "%6.4fA < %6.5fAavg < %6.4fA, "
- "%9.6fW < %9.6fWavg < %9.6fW\n",
- ch->channel_name, ch->min[0],
- ch->simple_avg[0] / ch->avg_count, ch->max[0],
- ch->min[1],
- ch->simple_avg[1] / ch->avg_count, ch->max[1],
- ch->min[2],
- ch->simple_avg[2] / ch->avg_count, ch->max[2]);
- }
- probe_close(&aep_context.aeps[m]);
+ fprintf(stderr, "%12s: %4.2fV < %4.3fVavg < %4.2fV, "
+ "%6.4fA < %6.5fAavg < %6.4fA, "
+ "%9.6fW < %9.6fWavg < %9.6fW\n",
+ aep_context.aep_shared->channel_name[n],
+ aep_context.aep_shared->min[n][0], aep_context.aep_shared->averages[n][0], aep_context.aep_shared->max[n][0],
+ aep_context.aep_shared->min[n][1], aep_context.aep_shared->averages[n][1], aep_context.aep_shared->max[n][1],
+ aep_context.aep_shared->min[n][2], aep_context.aep_shared->averages[n][2], aep_context.aep_shared->max[n][2]);
}
+ sem_close(aep_context.semaphore);
+
fprintf(stderr, "exited\n");
return 0;