The unified diff between revisions [afdbb938..] and [697c3a55..] is displayed below. It can also be downloaded as a raw diff.
This diff has been restricted to the following files: 'src/lsi/vm.c'
# # old_revision [afdbb9388305ae66464ad4acb0437922656e3059] # new_revision [697c3a55915ad7eda83ba73798ce0c4b8b2544ba] # # patch "src/lsi/vm.c" # from [bbb6e957a3bbc5fa4906c581c044dea5085cd39e] # to [6f62d2db74a2a4932bd876c11abeab092af42a19] # ============================================================ --- src/lsi/vm.c bbb6e957a3bbc5fa4906c581c044dea5085cd39e +++ src/lsi/vm.c 6f62d2db74a2a4932bd876c11abeab092af42a19 @@ -11,6 +11,7 @@ #include <fcntl.h> #include <errno.h> #include <math.h> +#include <stdarg.h> #include "vm.h" #include "code.h" @@ -21,6 +22,8 @@ #include "beatdetect.h" #include "map3d.h" #include "mouse.h" +#include "cmdsocket.h" +#include "sql.h" #define DEBUG 0 @@ -41,6 +44,9 @@ struct vm_thread { #define ARRAYBLOCKSIZE 512 +#define SLEEPTIME_SEC 60 +#define SLEEPTIME_NSEC 0 + struct pollfd vm_pollfd[VM_MAXPOLLFD]; int vm_pollfdqueue[VM_MAXPOLLFD]; @@ -55,6 +61,7 @@ size_t vm_codesize = 0; instr *vm_codearea = NULL; size_t vm_codesize = 0; +int vm_threads = 0; struct hashentry *fnhash[HASHSIZE]; struct hashentry *globhash[HASHSIZE]; @@ -67,79 +74,15 @@ struct hashentry *arrayhash[HASHSIZE]; #define GLOB_MAXNAMELEN 1024 -int vm_intfn_nop(void); -int vm_intfn_global_store(void); -int vm_intfn_global_load(void); -int vm_intfn_global_array_store(void); -int vm_intfn_global_array_load(void); -int vm_intfn_printint(void); -int vm_intfn_printreal(void); -int vm_intfn_printstr(void); -int vm_intfn_dmxsetchannel(void); -int vm_intfn_dmxoutput(void); -int vm_intfn_gettime(void); -int vm_intfn_waittime(void); -int vm_intfn_wait(void); -int vm_intfn_wakeup(void); -int vm_intfn_spawn(void); -int vm_intfn_midi_read(void); -int vm_intfn_beatdetect_read(void); -int vm_intfn_beatdetect_phase(void); -int vm_intfn_beatdetect_confidence(void); -int vm_intfn_realtoint(void); -int vm_intfn_inttoreal(void); -int vm_intfn_map3d_setcal(void); -int vm_intfn_map3d_calibrate(void); -int vm_intfn_map3d_transform(void); -int vm_intfn_map3d_setparams(void); -int vm_intfn_map3d_load(void); -int vm_intfn_map3d_save(void); -int vm_intfn_sin(void); -int vm_intfn_cos(void); -int vm_intfn_random(void); -int vm_intfn_mouse_read(void); void vm_destroy(struct vm_thread *); void vm_unqueue(struct vm_thread *); void vm_queue(struct vm_thread *, int); -typedef int (*vm_intfn)(void); +#include "abi.h" -vm_intfn vm_intfn_table[] = { - vm_intfn_nop, - vm_intfn_global_store, - vm_intfn_global_load, - vm_intfn_global_array_store, - vm_intfn_global_array_load, - vm_intfn_printint, - vm_intfn_printreal, - vm_intfn_printstr, - vm_intfn_dmxsetchannel, - vm_intfn_dmxoutput, - vm_intfn_gettime, - vm_intfn_waittime, - vm_intfn_wait, - vm_intfn_wakeup, - vm_intfn_spawn, - vm_intfn_midi_read, - vm_intfn_beatdetect_read, - vm_intfn_beatdetect_phase, - vm_intfn_beatdetect_confidence, - vm_intfn_realtoint, - vm_intfn_inttoreal, - vm_intfn_map3d_setcal, - vm_intfn_map3d_calibrate, - vm_intfn_map3d_transform, - vm_intfn_map3d_setparams, - vm_intfn_map3d_load, - vm_intfn_map3d_save, - vm_intfn_sin, - vm_intfn_cos, - vm_intfn_random, - vm_intfn_mouse_read, -}; +extern vm_intfn vm_intfn_table[]; +extern const int vm_intfn_size; -const int vm_intfn_size = sizeof(vm_intfn_table) / sizeof(vm_intfn); - void stack_push(struct vm_thread *thread, stkentry e); void stack_pop(struct vm_thread *thread, int count); stkentry stack_get(struct vm_thread *thread, int count); @@ -148,7 +91,7 @@ void stack_pokereal(struct vm_thread *th void stack_poke(struct vm_thread *thread, int count, stkentry value); void stack_pokereal(struct vm_thread *thread, int count, float value); -int vm_intfn_nop(void) +int vm_intfn___nop(void) { /* Do nothing */ return 1; @@ -159,7 +102,7 @@ int vm_intfn_nop(void) * The compiler does not allocate space for a return value. * They also change the stack pointer. */ -int vm_intfn_global_store(void) +int vm_intfn___global_store(void) { int len, next, value; struct hashentry *hashptr; @@ -194,7 +137,7 @@ gstoreout: return 1; } -int vm_intfn_global_load(void) +int vm_intfn___global_load(void) { int len, next, value; struct hashentry *hashptr; @@ -227,7 +170,7 @@ gloadout: return 1; } -int vm_intfn_global_array_store(void) +int vm_intfn___global_array_store(void) { int len, next, value, index; struct hashentry *hashptr; @@ -274,7 +217,7 @@ gstorearrayout: return 1; } -int vm_intfn_global_array_load(void) +int vm_intfn___global_array_load(void) { int len, next, value, index; struct hashentry *hashptr; @@ -482,6 +425,281 @@ int vm_intfn_mouse_read(void) return 0; } +int vm_intfn_cmdsocket_listen(void) +{ + stack_poke(vm_current, 0, + cmdsocket_listen(stack_get(vm_current, 1))); + return 1; +} + +int vm_intfn_cmdsocket_prefix(void) +{ + char buf[VM_STRING_MAX]; + int len = stack_get(vm_current, 1); + + strncpy(buf, stack_getstr(vm_current, len, 1), len); + buf[len] = '\0'; + + cmdsocket_prefix(buf); + + return 1; +} + +int vm_intfn_cmdsocket_accept(void) +{ + if (!cmdsocket_accept()) { + vm_queue(vm_current, VM_CMDLISTENQ); + vm_current = NULL; + return 0; + } + return 1; +} + +int vm_intfn_cmdsocket_read(void) +{ + if (!cmdsocket_read()) { + vm_queue(vm_current, VM_CMDREADQ); + vm_current = NULL; + return 0; + } + return 1; +} + +int vm_intfn_cmdsocket_write(void) +{ + int off = stack_get(vm_current, 1); + int len = stack_get(vm_current, 2); + char *buffer = stack_getstr(vm_current, len, 2); + int newoff; + + newoff = cmdsocket_write(buffer, len, off); + stack_poke(vm_current, 1, newoff); + + if (newoff != len) { + vm_queue(vm_current, VM_CMDWRITEQ); + vm_current = NULL; + return 0; + } + return 1; +} + +#ifdef NOT_YET + +#define MIN(a, b) ((a < b) ? a : b) + +#define MORE_QUERY_N(x, n) do { \ + off = strncpy(buf+off, (x), MIN(VM_STRING_MAX-off, (n)) - buf;\ + if (off >= VM_STRING_MAX) { \ + printf("Excessive string length - can't perform query\n"); \ + return 1; \ + } \ + } while (0) + +#define MORE_QUERY(x) MORE_QUERY_N((x), VM_STRING_MAX) + +int vm_intfn_sql_query(void) +{ + int nargs = stack_get(vm_current, 1); + int len = stack_get(vm_current, nargs+1); + char *fmt = stack_getstr(vm_current, len, nargs+1); + char buf1[VM_STRING_MAX]; + char buf2[VM_STRING_MAX]; + char buf[VM_STRING_MAX]; + int off = 0; + int result; + int next; + char *p, *p1; + + if (len > VM_STRING_MAX) { + printf("Excessive string length - can't perform query\n"); + return 1; + } + strncpy(buf1, fmt, len); + buf1[len] = '\0'; + + p = buf1; + while (p1 = strchr(p, '%') { + if (p1) { + *p1 = 0; + } + if (p != buf1) { + switch(*p) { + case '%': + MORE_QUERY("%"); + break; + case 's': + next = (len + sizeof(stkentry)-1) / sizeof(stkentry) + 1; + + MORE_QUERY_N(stack_getstr(vm_current, slen, nargs)); + } + } + MORE_QUERY(p); + if (p1) + p = p1; + else + break; + } + + sql_query(buffer, len, &result); + /* XXX what to do with an error here? */ + stack_poke(vm_current, 0, result); /* return value */ + return 1; +} +#else +int vm_intfn_sql_query(void) +{ + int len = stack_get(vm_current, 1); + char *query = stack_getstr(vm_current, len, 1); + int result; + + sql_query(query, len, &result); + /* XXX what to do with an error here? */ + stack_poke(vm_current, 0, result); /* return value */ + return 1; +} + +int vm_intfn_sql_query_1s(void) +{ + int len1, len2; + char buf1[VM_STRING_MAX]; + char buf2[VM_STRING_MAX]; + char query[VM_STRING_MAX]; + char *arg1; + char *arg2; + int result; + int next; + + next = 1; + + len2 = stack_get(vm_current, next); + arg2 = stack_getstr(vm_current, len2, next); + + next += (len2 + sizeof(stkentry)-1) / sizeof(stkentry) + 1; + + len1 = stack_get(vm_current, next); + arg1 = stack_getstr(vm_current, len1, next); + + if ((len1 > VM_STRING_MAX) || (len2 > VM_STRING_MAX)) { + printf("Excessive string length - can't perform query\n"); + return 1; + } + strncpy(buf1, arg1, len1); + buf1[len1] = '\0'; + strncpy(buf2, arg2, len2); + buf2[len2] = '\0'; + + snprintf(query, VM_STRING_MAX, buf1, buf2); + + sql_query(query, strlen(query), &result); + + /* XXX what to do with an error here? */ + stack_poke(vm_current, 0, result); /* return value */ + return 1; +} + +int vm_intfn_sql_getvar(void) +{ + int len; + char buf[VM_STRING_MAX]; + char query[VM_STRING_MAX]; + int result; + + len = stack_get(vm_current, 1); + + if (len >= VM_STRING_MAX) { + printf("Excessive string length - can't perform query\n"); + return 1; + } + + snprintf(buf, len+1, stack_getstr(vm_current, len, 1)); + snprintf(query, VM_STRING_MAX, "SELECT value FROM vars WHERE name=\"%s\"", buf); + + if (sql_query(query, strlen(query), &result) != 2) + result = -1; + + /* XXX what to do with an error here? */ + stack_poke(vm_current, 0, result); /* return value */ + return 1; +} + +int vm_intfn_sql_getvar_array(void) +{ + int len, off; + char buf[VM_STRING_MAX]; + char query[VM_STRING_MAX]; + int result; + + off = stack_get(vm_current, 1); + len = stack_get(vm_current, 2); + + if (len >= VM_STRING_MAX) { + printf("Excessive string length - can't perform query\n"); + return 1; + } + + snprintf(buf, len+1, stack_getstr(vm_current, len, 2)); + snprintf(query, VM_STRING_MAX, "SELECT value FROM vars WHERE name=\"%s[%d]\"", buf, off); + + if (sql_query(query, strlen(query), &result) != 2) + result = -1; + + /* XXX what to do with an error here? */ + stack_poke(vm_current, 0, result); /* return value */ + return 1; +} + +int vm_intfn_sql_setvar(void) +{ + int len, val; + char buf[VM_STRING_MAX]; + char query[VM_STRING_MAX]; + int result; + + val = stack_get(vm_current, 1); + len = stack_get(vm_current, 2); + + if (len >= VM_STRING_MAX) { + printf("Excessive string length - can't perform query\n"); + return 1; + } + + snprintf(buf, len+1, stack_getstr(vm_current, len, 2)); + snprintf(query, VM_STRING_MAX, "INSERT OR REPLACE INTO vars VALUES(\"%s\", %d)", buf, val); + + sql_query(query, strlen(query), &result); + + /* XXX what to do with an error here? */ + stack_poke(vm_current, 0, result); /* return value */ + return 1; +} + +int vm_intfn_sql_setvar_array(void) +{ + int len, off, val; + char buf[VM_STRING_MAX]; + char query[VM_STRING_MAX]; + int result; + + val = stack_get(vm_current, 1); + off = stack_get(vm_current, 2); + len = stack_get(vm_current, 3); + + if (len >= VM_STRING_MAX) { + printf("Excessive string length - can't perform query\n"); + return 1; + } + + snprintf(buf, len+1, stack_getstr(vm_current, len, 3)); + snprintf(query, VM_STRING_MAX, "INSERT OR REPLACE INTO vars VALUES(\"%s[%d]\", %d)", buf, off, val); + + sql_query(query, strlen(query), &result); + + /* XXX what to do with an error here? */ + stack_poke(vm_current, 0, result); /* return value */ + return 1; +} +#endif + int vm_intfn_beatdetect_read(void) { if (!beatdetect_read()) { @@ -634,6 +852,7 @@ void vm_init(void) vm_npollfds = 0; vm_caughtsignal = 0; signal(SIGIO, vm_sighandler); + signal(SIGPIPE, SIG_IGN); } void vm_load_file(char *filename) @@ -642,7 +861,9 @@ void vm_load_file(char *filename) char *ptr; fh = fopen(filename, "r"); - assert(fh != NULL); + if (fh == NULL) { + err(1, "Failed to open '%s'", filename); + } for (ptr = vm_codearea; ptr < vm_codearea+vm_codesize; ptr++) { int c; @@ -668,11 +889,19 @@ void vm_init_functions(void) struct hashentry *ptr; /* First, let's check the magic */ - assert(vm_codearea[0] == MAGIC1); - assert(vm_codearea[1] == MAGIC2); - assert(vm_codearea[2] == VERSION1); - assert(vm_codearea[3] == VERSION2); + if ((vm_codearea[0] != MAGIC1) || + (vm_codearea[1] != MAGIC2)) + errx(1, "Bad magic - not a lightscript binary"); + if ((vm_codearea[2] != VERSION1) || + (vm_codearea[3] != VERSION2)) + errx(1, "Bad version - recompile"); + if ((GETINT(vm_codearea, 8) != vm_abiversion1) || + (GETINT(vm_codearea, 12) == vm_abiversion2) || + (GETINT(vm_codearea, 16) == vm_abiversion3) || + (GETINT(vm_codearea, 20) == vm_abiversion4) || + (GETINT(vm_codearea, 24) == vm_abiversion5)) + errx(1, "Incompatible ABI version - recompile"); /* Now, get the function table pointer */ t = GETINT(vm_codearea, 4); @@ -732,10 +961,11 @@ void vm_queue(struct vm_thread *thread, vm_queues[queue] = thread; } -int vm_spawn(char *fn) +int vm_spawn_args(char *fn, int n, ...) { struct vm_thread *newt; struct hashentry *ptr; + va_list ap; ptr = hash_lookup(fnhash, fn, 0); if (ptr == NULL) { @@ -761,25 +991,46 @@ int vm_spawn(char *fn) return 0; } newt->sp = newt->stackbase; + + stack_push(newt, 0); /* Return value */ + + /* Push optional arguments */ + va_start(ap, n); + while (n--) { + int a = va_arg(ap, int); +// printf("arg is %d\n", a); + stack_push(newt, a); + } + va_end(ap); + /* Push return address here, to point to some special thread exit routine */ - - stack_push(newt, 0); /* Return value */ stack_push(newt, 0); /* Return address */ /* Insert into head of run queue */ newt->prev = NULL; newt->queue = VM_NOQUEUE; vm_queue(newt, VM_RUNQ); + vm_threads++; return 1; } +int vm_spawn(char *fn) +{ + return vm_spawn_args(fn, 0); +} + void vm_destroy(struct vm_thread *thread) { vm_unqueue(thread); free(thread->stackbase); free(thread); + vm_threads--; + if (vm_threads == 0) { + printf("No threads left\n"); + exit(0); + } } int vm_runnable(struct vm_thread *thread) @@ -816,18 +1067,19 @@ void vm_sched(void) struct timespec ts; int rv; - if (vm_queues[VM_TIMEQ] == NULL) { - printf("No runnable thread, and no waiting thread\n"); - exit(0); - } // printf("No runnable thread - sleeping\n"); - gettimeofday(&tv, NULL); - timersub(&vm_queues[VM_TIMEQ]->time, &tv, &tv); - if ((tv.tv_sec < 0) || (tv.tv_usec < 0)) { - tv.tv_sec = 0; - tv.tv_usec = 0; + if (vm_queues[VM_TIMEQ]) { + gettimeofday(&tv, NULL); + timersub(&vm_queues[VM_TIMEQ]->time, &tv, &tv); + if ((tv.tv_sec < 0) || (tv.tv_usec < 0)) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + TIMEVAL_TO_TIMESPEC(&tv, &ts); + } else { + ts.tv_sec = SLEEPTIME_SEC; + ts.tv_nsec = SLEEPTIME_NSEC; } - TIMEVAL_TO_TIMESPEC(&tv, &ts); // nanosleep(&ts, NULL); rv = pollts(vm_pollfd, vm_npollfds, &ts, NULL); if ((rv == -1) && (errno != EINTR)) @@ -850,6 +1102,20 @@ void vm_register_signal_fd(int fd, int q rv = fcntl(fd, F_SETFL, O_NONBLOCK | O_ASYNC); } +void vm_unregister_signal_fd(int fd) +{ + int i; + + for (i = 0; i < vm_npollfds; i++) { + if (fd == vm_pollfd[i].fd) { + memmove(&vm_pollfd[i], &vm_pollfd[i+1], + sizeof(struct pollfd) * (vm_npollfds-i-1)); + vm_npollfds--; + return; + } + } +} + void stack_push(struct vm_thread *thread, stkentry e) { thread->sp++;