diff --git a/ChangeLog b/ChangeLog index 020c83e023..b6620afc3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1632,4 +1632,6 @@ from sched/ to lib/pthread where they more appropriately belong. * sched/ and lib/semaphore/: Move some semaphore-related interfaces from sched/ to lib/pthread where they more appropriately belong. - * syscall/: The beginnings of an options syscall interface. + * syscall/: The beginnings of an optional syscall kernal interface. + * tools/mksyscall.c: Add a tool that will auto-generate syscall proxies + and stubs from a comma-separated-value (CSV) data file. diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index 007924d2f7..224b1bef81 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -8,7 +8,7 @@

NuttX RTOS

-

Last Updated: March 28, 2011

+

Last Updated: March 30, 2011

@@ -2176,6 +2176,18 @@ nuttx-6.1 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> of the nuttx source tree * apps/namedapp/binfs.c: Create a tiny filesystem that can be used to show the internal named apps under /bin. + * fs/fs_opendir.c: Correct an error that occurs when a file system is + mounted in the root directory. This was discovered while mounting + the named app's /bin directory. + * lib/: Move all source files into a subdirectory of lib/ named after + the header file in which the library function is prototyped. + * sched/ and lib/pthread/: Move pthread attribute-related interfaces + from sched/ to lib/pthread where they more appropriately belong. + * sched/ and lib/semaphore/: Move some semaphore-related interfaces + from sched/ to lib/pthread where they more appropriately belong. + * syscall/: The beginnings of an optional syscall kernel interface. + * tools/mksyscall.c: Add a tool that will auto-generate syscall proxies + and stubs from a comma-separated-value (CSV) data file. apps-6.1 2011-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/lib/semaphore/Make.defs b/lib/semaphore/Make.defs index 7ea64b20e3..996d320fea 100644 --- a/lib/semaphore/Make.defs +++ b/lib/semaphore/Make.defs @@ -33,4 +33,4 @@ # ############################################################################ -SEM_SRCS = sem_init.c sem_getvalue.c sem_destroy.c +SEM_SRCS = sem_init.c sem_getvalue.c diff --git a/lib/semaphore/sem_getvalue.c b/lib/semaphore/sem_getvalue.c index e1ad9ac0d6..bc9971b201 100644 --- a/lib/semaphore/sem_getvalue.c +++ b/lib/semaphore/sem_getvalue.c @@ -39,6 +39,7 @@ #include +#include #include #include diff --git a/lib/semaphore/sem_init.c b/lib/semaphore/sem_init.c index c75281bf07..f4c9a0d8b5 100644 --- a/lib/semaphore/sem_init.c +++ b/lib/semaphore/sem_init.c @@ -39,6 +39,7 @@ #include +#include #include #include #include diff --git a/sched/Makefile b/sched/Makefile index ab83a8fee8..04bfdd57bb 100644 --- a/sched/Makefile +++ b/sched/Makefile @@ -115,7 +115,7 @@ ifneq ($(CONFIG_DISABLE_SIGNALS),y) PTHREAD_SRCS += pthread_condtimedwait.c pthread_kill.c pthread_sigmask.c endif -SEM_SRCS = sem_initialize.c sem_open.c sem_close.c sem_unlink.c \ +SEM_SRCS = sem_initialize.c sem_destroy.c sem_open.c sem_close.c sem_unlink.c \ sem_wait.c sem_trywait.c sem_post.c sem_findnamed.c ifneq ($(CONFIG_DISABLE_SIGNALS),y) SEM_SRCS += sem_waitirq.c diff --git a/lib/semaphore/sem_destroy.c b/sched/sem_destroy.c similarity index 99% rename from lib/semaphore/sem_destroy.c rename to sched/sem_destroy.c index 0d4fb92712..95db46468f 100644 --- a/lib/semaphore/sem_destroy.c +++ b/sched/sem_destroy.c @@ -42,6 +42,8 @@ #include #include +#include "sem_internal.h" + /**************************************************************************** * Definitions ****************************************************************************/ diff --git a/syscall/README.txt b/syscall/README.txt index bfaabcc65d..d4d0323acd 100644 --- a/syscall/README.txt +++ b/syscall/README.txt @@ -97,11 +97,30 @@ Auto-Generated Files Stubs and proxies for the sycalls are automatically generated from this CSV database. Here the following definition is used: - STUB - A tiny bit of code that executes with within the NuttX kernel that - is used to map a software interrupt received by the kernel to a - kernel function call. - - Proxy - Another tiny bit of code that executes in the user space. A proxy + Proxy - A tiny bit of code that executes in the user space. A proxy has exactly the same function prototype as does the "real" function for which it proxies. However, it only serves to map the function - call into a syscall, marshalling all of the parameters as necessary. + call into a syscall, marshalling all of the system call parameters + as necessary. + + STUB - Another tiny bit of code that executes within the NuttX kernel + that is used to map a software interrupt received by the kernel to + a kernel function call. The stubs receive the marshalled system + call data, and perform the actually kernel function call (in + kernel-mode) on behalf of the proxy function. + +Sub-Directories +=============== + + stubs - Autogenerated stub files are placed in this directory. + proxies - Autogenerated proxy files are placed in this directory. + +mksyscall +========= + + mksyscall is C program that is used used during the initial NuttX build + by the logic in the top-level syscall/ directory. Information about the + stubs and proxies is maintained in a comma separated value (CSV) file + in the syscall/ directory. The mksyscall program will accept this CVS + file as input and generate all of the required proxy or stub files as + output. See tools/README.txt for additonal information. diff --git a/syscall/proxies/Make.defs b/syscall/proxies/Make.defs new file mode 100644 index 0000000000..3f1c01b2c9 --- /dev/null +++ b/syscall/proxies/Make.defs @@ -0,0 +1,36 @@ +############################################################################ +# syscall/proxies/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +PROXY_SRCS := ${shell ls *.c} diff --git a/syscall/stubs/Make.defs b/syscall/stubs/Make.defs new file mode 100644 index 0000000000..7237ddded5 --- /dev/null +++ b/syscall/stubs/Make.defs @@ -0,0 +1,36 @@ +############################################################################ +# syscall/stubs/Make.defs +# +# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +STUB_SRCS := ${shell ls *.c} diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 7cb60003a8..3dffa4ad4e 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -104,6 +104,7 @@ "seekdir","dirent.h","void","FAR DIR*","off_t" "select","sys/select.h","int","int","FAR fd_set*","FAR fd_set*","FAR fd_set*","FAR struct timeval*" "sem_close","semaphore.h","int","FAR sem_t*" +"sem_destroy","semaphore.h","int","FAR sem_t*" "sem_open","semaphore.h","FAR sem_t*","FAR const char*","int","..." "sem_post","semaphore.h","int","FAR sem_t*" "sem_trywait","semaphore.h","int","FAR sem_t*" diff --git a/tools/Makefile.host b/tools/Makefile.host index a5a83d4ae3..95cf64c680 100644 --- a/tools/Makefile.host +++ b/tools/Makefile.host @@ -35,12 +35,19 @@ all: mkconfig mksyscall default: mkconfig mksyscall +.PHONY: clean + +# Add CFLAGS=-g on the make command line build debug versions CFLAGS = -O2 -Wall +# mkconfig - Convert a .config file into a C config.h file + mkconfig: mkconfig.c @gcc $(CFLAGS) -o mkconfig mkconfig.c +# mksyscall - Convert a CSV file into syscall stubs and proxies + mksyscall: mksyscall.c @gcc $(CFLAGS) -o mksyscall mksyscall.c diff --git a/tools/README.txt b/tools/README.txt index 5e7edaf4f8..76ec3a66fe 100755 --- a/tools/README.txt +++ b/tools/README.txt @@ -31,17 +31,39 @@ mkconfig.c into include/nuttx/config.h. config.h is a another version of the NuttX configuration that can be included by C files. +mksyscall.c + + This is C file that is used to build mksyscall program. The mksyscall + program is used during the initial NuttX build by the logic in the top- + level syscall/ directory. + + If you build NuttX as a separately compiled, monolithic kernel and separate + applications, then there is a syscall layer that is used to get from the + user application space to the NuttX kernel space. In the user application + "proxies" for each of the kernel functions are provided. The proxies have + the same function signature as the kernel function, but only execute a + system call. + + Within the kernel, there are "stubs" for each of the system calls. The + stubs receive the marshalled system call data, and perform the actually + kernel function call (in kernel-mode) on behalf of the proxy function. + + Information about the stubs and proxies is maintained in a comma separated + value (CSV) file in the syscall/ directory. The mksyscall program will + accept this CVS file as input and generate all of the required proxy or + stub files as output. See syscall/README.txt for additonal information. + +Makefile.host + + This is the makefile that is used to make the mkconfig program from + the mkconfig.c C file or the mksyscall program from the mksyscall.c file. + mkromfsimg.sh This script may be used to automate the generate of a ROMFS file system image. It accepts an rcS script "template" and generates and image that may be mounted under /etc in the NuttX pseudo file system. -Makefile.mkconfig - - This is the makefile that is used to make the mkconfig program from - the mkconfig.c C file. - mkdeps.sh mknulldeps.sh diff --git a/tools/mksyscall.c b/tools/mksyscall.c new file mode 100644 index 0000000000..10eb65ac34 --- /dev/null +++ b/tools/mksyscall.c @@ -0,0 +1,433 @@ +/**************************************************************************** + * tools/mksyscall.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define LINESIZE (PATH_MAX > 256 ? PATH_MAX : 256) + +#define MAX_FIELDS 16 +#define MAX_PARMSIZE 128 +#define NAME_INDEX 0 +#define HEADER_INDEX 1 +#define RETTYPE_INDEX 2 +#define PARM1_INDEX 3 + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static bool g_debug; +static char g_line[LINESIZE+1]; +static char g_parm[MAX_FIELDS][MAX_PARMSIZE]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static char *skip_space(char *ptr) +{ + while (*ptr && isspace(*ptr)) ptr++; + return ptr; +} + +static char *read_line(FILE *stream) +{ + char *ptr; + + for (;;) + { + g_line[LINESIZE] = '\0'; + if (!fgets(g_line, LINESIZE, stream)) + { + return NULL; + } + else + { + if (g_debug) + { + printf("Line: %s\n", g_line); + } + + ptr = skip_space(g_line); + if (*ptr && *ptr != '#' && *ptr != '\n') + { + return ptr; + } + } + } +} + +static char *copy_parm(char *src, char *dest) +{ + char *start = src; + int i; + + for (i = 0; i < MAX_PARMSIZE; i++) + { + if (*src == '"') + { + *dest = '\0'; + return src; + } + else if (*src == '\n' || *src == '\0') + { + fprintf(stderr, "Unexpected end of line: \"%s\"\n", start); + exit(4); + } + else + { + *dest++ = *src++; + } + } + + fprintf(stderr, "Parameter too long: \"%s\"\n", start); + exit(3); +} + +static char *find_parm(char *ptr) +{ + char *start = ptr; + + if (*ptr != '"') + { + fprintf(stderr, "I'm confused: \"%s\"\n", start); + exit(5); + } + ptr++; + + ptr = skip_space(ptr); + if (*ptr == '\n' || *ptr == '\0') + { + return NULL; + } + else if (*ptr != ',') + { + fprintf(stderr, "Expected ',': \"%s\"\n", start); + exit(6); + } + ptr++; + + ptr = skip_space(ptr); + if (*ptr != '"') + { + fprintf(stderr, "Expected \": \"%s\"\n", start); + exit(7); + } + ptr++; + + return ptr; +} + +static int parse_csvline(char *ptr) +{ + int nparms; + int i; + + /* Format "arg1","arg2","arg3",... Spaces will be tolerated outside of the + * quotes. Any initial spaces have already been skipped so the first thing + * should be '"'. + */ + + if (*ptr != '"') + { + fprintf(stderr, "Bad line: \"%s\"\n", g_line); + exit(2); + } + + ptr++; + nparms = 0; + + do + { + ptr = copy_parm(ptr, &g_parm[nparms][0]); + nparms++; + ptr = find_parm(ptr); + } + while (ptr); + + if (g_debug) + { + printf("Parameters: %d\n", nparms); + for (i = 0; i < nparms; i++) + { + printf(" Parm%d: \"%s\"\n", i+1, g_parm[i]); + } + } + return nparms; +} + +static FILE *open_proxy(void) +{ + char filename[MAX_PARMSIZE+4]; + FILE *stream; + + snprintf(filename, MAX_PARMSIZE+3, "%s.c", g_parm[NAME_INDEX]); + filename[MAX_PARMSIZE+3] = '\0'; + + stream = fopen(filename, "w"); + if (stream == NULL) + { + fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); + exit(10); + } + return stream; +} + +static void generate_proxy(int nparms) +{ + FILE *stream = open_proxy(); + int i; + + fprintf(stream, "/* Auto-generated %s proxy file -- do not edit */\n\n", g_parm[NAME_INDEX]); + fprintf(stream, "#include <%s>\n\n", g_parm[HEADER_INDEX]); + + fprintf(stream, "%s %s(", g_parm[RETTYPE_INDEX], g_parm[NAME_INDEX]); + + if (nparms <= 0) + { + fprintf(stream, "void"); + } + else + { + for (i = 0; i < nparms; i++) + { + if (i > 0) + { + fprintf(stream, ", %s parm%d", g_parm[PARM1_INDEX+i], i+1); + } + else + { + fprintf(stream, "%s parm%d", g_parm[PARM1_INDEX+i], i+1); + } + } + } + + fprintf(stream, ")\n{\n"); + fprintf(stream, " return (%s)sys_call%d(", g_parm[RETTYPE_INDEX], nparms); + for (i = 0; i < nparms; i++) + { + if (i > 0) + { + fprintf(stream, ", (uintptr_t)parm%d", i+1); + } + else + { + fprintf(stream, "(uintptr_t)parm%d", i+1); + } + } + fprintf(stream, ");\n}\n"); + fclose(stream); +} + +static FILE *open_stub(void) +{ + char filename[MAX_PARMSIZE+8]; + FILE *stream; + + snprintf(filename, MAX_PARMSIZE+7, "STUB_%s.c", g_parm[NAME_INDEX]); + filename[MAX_PARMSIZE+7] = '\0'; + + stream = fopen(filename, "w"); + if (stream == NULL) + { + fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno)); + exit(9); + } + return stream; +} + +static void generate_stub(int nparms) +{ + FILE *stream = open_stub(); + int i; + + fprintf(stream, "/* Auto-generated %s stub file -- do not edit */\n\n", g_parm[0]); + fprintf(stream, "#include <%s>\n\n", g_parm[HEADER_INDEX]); + fprintf(stream, "uintptr_t STUB_%s(", g_parm[NAME_INDEX]); + + if (nparms <= 0) + { + fprintf(stream, "void"); + } + else + { + for (i = 0; i < nparms; i++) + { + if (i > 0) + { + fprintf(stream, ", uintptr_t parm%d", i+1); + } + else + { + fprintf(stream, "uintptr_t parm%d", i+1); + } + } + } + + fprintf(stream, ")\n{\n"); + fprintf(stream, " return (uintptr_t)%s(", g_parm[NAME_INDEX]); + for (i = 0; i < nparms; i++) + { + if (i > 0) + { + fprintf(stream, ", (%s)parm%d", g_parm[PARM1_INDEX+i], i+1); + } + else + { + fprintf(stream, "(%s)parm%d", g_parm[PARM1_INDEX+i], i+1); + } + } + fprintf(stream, ");\n}\n"); + fclose(stream); +} + +static void show_usage(const char *progname) +{ + fprintf(stderr, "USAGE: %s [-p|s] \n", progname); + exit(1); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, char **argv, char **envp) +{ + char *csvpath; + bool proxies = false; + FILE *stream; + char *ptr; + int ch; + + /* Parse command line options */ + + g_debug = false; + + while ((ch = getopt(argc, argv, ":dps")) > 0) + { + switch (ch) + { + case 'd' : + g_debug = true; + break; + + case 'p' : + proxies = true; + break; + + case 's' : + proxies = false; + break; + + case '?' : + fprintf(stderr, "Unrecognized option: %c\n", optopt); + show_usage(argv[0]); + + case ':' : + fprintf(stderr, "Missing option argument, option: %c\n", optopt); + show_usage(argv[0]); + + break; + fprintf(stderr, "Unexpected option: %c\n", ch); + show_usage(argv[0]); + } + } + + if (optind >= argc) + { + fprintf(stderr, "Missing \n"); + show_usage(argv[0]); + } + + csvpath = argv[optind]; + if (++optind < argc) + { + fprintf(stderr, "Unexpected garbage at the end of the line\n"); + show_usage(argv[0]); + } + + /* Open the CSV file */ + + stream= fopen(csvpath, "r"); + if (!stream) + { + fprintf(stderr, "open %s failed: %s\n", csvpath, strerror(errno)); + exit(3); + } + + /* Process each line in the CVS file */ + + while ((ptr = read_line(stream)) != NULL) + { + /* Parse the line from the CVS file */ + + int nargs = parse_csvline(ptr); + if (nargs < 3) + { + fprintf(stderr, "Only %d arguments found: %s\n", nargs, g_line); + exit(8); + } + + if (proxies) + { + generate_proxy(nargs-3); + } + else + { + generate_stub(nargs-3); + } + } + + /* Close the CSV file */ + + fclose(stream); + return 0; +}