diff --git a/apps/jacobi.c b/apps/jacobi.c index c111c495..cbeebcc4 100644 --- a/apps/jacobi.c +++ b/apps/jacobi.c @@ -28,7 +28,7 @@ #include "tests.h" -#ifdef START_KERNEL_JACOBI +#if (defined(START_KERNEL_JACOBI) || defined(START_CHIEFTEST)) && defined(CONFIG_ROCKCREEK) #define MATRIX_SIZE 256 #define MAXVALUE 1337 @@ -353,14 +353,17 @@ int jacobi(void* argv) * check the result * X[i] have to be 1 */ + int err=0; for(i=0; i 0.01) + if (error > 0.01) { kprintf("Result is on position %d wrong (%d/10000 != 1.0, error %d/10000)\n", i, (int) (10000.0*X[i]), (int) (10000.0*error)); + err = 1; + } } kprintf("maximal error is %d/10000\n", (int) (10000.0*max)); @@ -368,7 +371,7 @@ int jacobi(void* argv) kprintf("number of iterations: %d\n", iterations); kprintf("Calculation time: %llu ms (%llu ticks)\n", (stop-start)/(1000ULL*get_cpu_frequency()), stop-start); - return 0; + return err; } #endif diff --git a/apps/netio.c b/apps/netio.c index 8f51589c..3d57cb32 100644 --- a/apps/netio.c +++ b/apps/netio.c @@ -48,7 +48,7 @@ /* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */ -#if defined(START_NETIO) && defined(CONFIG_LWIP) +#if (defined(START_NETIO) || defined(START_CHIEFTEST)) && defined(CONFIG_LWIP) #ifdef CONFIG_ROCKCREEK #if USE_SOCKET_BYPASSING // for socket bypassing #include diff --git a/apps/tests.c b/apps/tests.c index 4164ec5b..15b28e14 100644 --- a/apps/tests.c +++ b/apps/tests.c @@ -46,7 +46,7 @@ int jacobi(void* arg); void echo_init(void); void netio_init(void); -#ifdef START_CONSUMER_PRODUCER +#if defined(START_CONSUMER_PRODUCER) || defined(START_CHIEFTEST) static sem_t consuming, producing; static mailbox_int32_t mbox; static int val = 0; @@ -89,9 +89,28 @@ static int producer(void* arg) return 0; } + +static int producer_consumer(void) +{ + tid_t id1, id2, ret; + int result1, result2, result; + + create_kernel_task(&id1, producer, NULL, NORMAL_PRIO); + create_kernel_task(&id2, consumer, NULL, NORMAL_PRIO); + + ret = wait(&result); + if (ret == id1) result1 = result; + else result2 = result; + + ret = wait(&result); + if (ret == id1) result1 = result; + else result2 = result; + + return result1 || result2; +} #endif -#if defined(START_FOO) || defined(START_JOIN_TEST) +#if defined(START_FOO) || defined(START_JOIN_TEST) || defined(START_CHIEFTEST) static int foo(void* arg) { int i; @@ -108,7 +127,7 @@ static int foo(void* arg) } #endif -#ifdef START_MAIL_PING +#if (defined(START_MAIL_PING) || defined(START_CHIEFTEST)) && defined(CONFIG_ROCKCREEK) static int mail_ping(void* arg) { int i; @@ -132,7 +151,7 @@ static int mail_noise(void*arg) { } #endif -#ifdef START_SVM_TEST +#if (defined(START_SVM_TEST) || defined(START_CHIEFTEST)) && defined(CONFIG_ROCKCREEK) /* N has to be multiple of UEs */ @@ -173,6 +192,8 @@ static int svm_test(void *arg) if (!my_ue) { // allocate and initialize SVM region A[0] = (int*) kmalloc(3*N*N*sizeof(int)); + if (!A[0]) + return 1; // Let the others hang in the barrier. People will notice that things went wrong. memset((void*) A[0], 0x00, 3*N*N*sizeof(int)); // initialize matrices @@ -188,7 +209,7 @@ static int svm_test(void *arg) GET_B(i,j) = i+j; } - kputs("Start sequentiell calculation...\n"); + kputs("Start sequential calculation...\n"); start = rdtsc(); start = rdtsc(); @@ -203,7 +224,6 @@ static int svm_test(void *arg) } } - end = rdtsc(); kprintf("Calculation time (seq): %llu ms (%llu ticks)\n", (end-start)/(1000ULL*get_cpu_frequency()), end-start); @@ -222,6 +242,8 @@ static int svm_test(void *arg) kputs("Use Strong Release consistency!\n"); A[0] = (int*) svm_malloc(3*N*N*sizeof(int), svm_flags); + if (!A[0]) + return 1; #if 1 if (!my_ue) @@ -281,9 +303,8 @@ static int svm_test(void *arg) kputs("Check results...\n"); + uint32_t err = 0; // Be paranoid for a test case. return != 0 if calculation was not correct. if (!my_ue) { - uint32_t err = 0; - svm_invalidate(); for(i=0; (i 1) { + int i; + for (i=0; i < 6; i++) + // Need as many barriers for the other cores as they occur in the benchmark. + svm_barrier(SVM_TYPE); + return 0; + } + return svm_bench(NULL); +} #endif -#ifdef START_JOIN_TEST +#if defined(START_JOIN_TEST) || defined(START_CHIEFTEST) static int join_test(void* arg) { tid_t id, ret; @@ -397,7 +438,7 @@ static int join_test(void* arg) kprintf("Child %u finished: result = %d\n", id, result); - return 0; + return result != 42; } #endif @@ -453,6 +494,8 @@ static int measure_ctx_switch(void* arg) for (i=0; i < REPS && stop == 0; i++) { while(id == sid && stop == 0) { t2 = rdtsc(); + // Calling rdtsc that often it is better + // to serialize the calls in the pipeline. cpuid(0,&a,&b,&c,&d); } @@ -489,6 +532,99 @@ next_try: } #endif +#ifdef START_CHIEFTEST + +struct testcase_t { + tid_t tid; + int retval; + char* userspace_argv[10]; + entry_point_t kernelspace_ep; + char* testcase_name; +}; + +#define USERSPACE_TC(execpath, name) {0, 0, {execpath, NULL}, NULL, name} +#define KERNELSPACE_TC(execpointer, name) {0, 0, {NULL}, execpointer, name} + +struct testcase_t testcases[] = { + USERSPACE_TC("/bin/jacobi", "Jacobi serial user space app"), + USERSPACE_TC("/bin/tests", "Tests user space app"), + USERSPACE_TC("/bin/hello", "Hello userspace app"), + KERNELSPACE_TC(producer_consumer, "Producer consumer kernel space test"), + KERNELSPACE_TC(join_test, "Join kernel space test"), +#ifdef CONFIG_ROCKCREEK + KERNELSPACE_TC(svm_test, "SVM Test kernel space test"), + KERNELSPACE_TC(testcase_svm_bench, "SVM Bench kernel space test"), + KERNELSPACE_TC(mail_ping, "Mail Ping kernel space test"), +// KERNELSPACE_TC(jacobi, "Jacobi kernel space test"), + KERNELSPACE_TC(netio_init, "NetIO kernel space test") +#endif +}; + +static int chiefmastertest(void) +{ + int tests = sizeof(testcases) / sizeof(struct testcase_t); + int i; + int result; + tid_t id, ret; + struct testcase_t* current; + + kprintf("Starting chief master test: %d test cases.\n", tests); + + for (i = 0; i < tests; i++) { + current = &testcases[i]; + +#ifdef CONFIG_ROCKCREEK + RCCE_barrier(&RCCE_COMM_WORLD); +#endif + kprintf("Starting testcase: %s\n", current->testcase_name); + + if (current->kernelspace_ep == NULL && + current->userspace_argv[0] != NULL) { + create_user_task(¤t->tid, current->userspace_argv[0], + current->userspace_argv); + } else if (current->kernelspace_ep != NULL && + current->userspace_argv[0] == NULL) { + create_kernel_task(¤t->tid, current->kernelspace_ep, + NULL, NORMAL_PRIO); + } else { + kprintf("Invalid test case struct #%d!\n", i); + continue; + } + + do { + ret = wait(&result); + } while(ret != current->tid); + + kprintf("Testcase %s returned %d %s\n", current->testcase_name, result, result ? ":(" : ":)"); + + current->retval = result; + } + + + kprintf("======================================================\n"); + kprintf("Master Chief test case results:\n"); + for (i = 0; i < tests; i++) { + current = &testcases[i]; + + kprintf("%s: ", current->testcase_name); + if (current->retval) { + pushfg(COL_RED); + kprintf("Bad :("); + } else { + pushfg(COL_GREEN); + kprintf("Pass :)"); + } + popfg(); + popbg(); + kprintf("\n"); + } + kprintf("======================================================\n"); + + return 0; +} + +#endif // START_CHIEFTEST + int test_init(void) { #ifdef START_HELLO @@ -505,19 +641,23 @@ int test_init(void) char* client_argv[] = {"/bin/client", "192.168.0.1", "6789", NULL}; #endif +#ifdef START_CHIEFTEST + create_kernel_task(NULL, chiefmastertest, NULL, NORMAL_PRIO); +#endif + #ifdef START_ECHO echo_init(); #endif #ifdef START_NETIO netio_init(); #endif -#ifdef START_CONSUMER_PRODUCER +#if defined(START_CONSUMER_PRODUCER) || defined(START_CHIEFTEST) sem_init(&producing, 1); sem_init(&consuming, 0); mailbox_int32_init(&mbox); - - create_kernel_task(NULL, producer, NULL, NORMAL_PRIO); - create_kernel_task(NULL, consumer, NULL, NORMAL_PRIO); +#endif +#ifdef START_CONSUMER_PRODUCER + create_kernel_task(NULL, producer_consumer, NULL, NORMAL_PRIO); #endif #ifdef START_MEASURE_CTX_SWITCH create_kernel_task(NULL, measure_ctx_switch, (int)0, NORMAL_PRIO); diff --git a/apps/tests.h b/apps/tests.h index fb27e1c8..5df3b382 100644 --- a/apps/tests.h +++ b/apps/tests.h @@ -47,6 +47,8 @@ #define START_TESTS //#define START_JACOBI +//#define START_CHIEFTEST + // does our demos require GFX support? //#define CONFIG_GFX diff --git a/documentation/text/benchmarks.dox b/documentation/text/benchmarks.dox new file mode 100644 index 00000000..6df5a8ee --- /dev/null +++ b/documentation/text/benchmarks.dox @@ -0,0 +1,161 @@ +/** + * @file benchmarks.dox + * @page benchmarks Benchmarks and Example Applications + * + * + * @section toc Table of Contents + * - @ref scc_ks + * - @ref general_ks + * - @ref general_us + * + * @section kernelspace Kernel Space Applications/Benchmarks + * Located in: `apps/` + * + * You can activate/deactivate the start of these applications after booting MetalSVM + * using the \c \#define flags in `apps/tests.h`. + * The configuration looks like (Just remove the comment prefix from the applications + * you would like to start): + * \code + ... +//#define START_SVM_TEST +#define START_SVM_BENCH +//#define START_MAIL_PING +#define START_MAIL_NOISE +//#define START_KERNEL_LAPLACE +//#define START_KERNEL_JACOBI + ... + * \endcode + * + * There are SCC-specific as well as generic kernel space applications and benchmarks. + * Most of these applications are located in `apps/tests.c`, unless otherwise noted: + * + * @subsection scc_ks SCC-specific + * + * - __SVM_TEST__: This application creates three matrices A, B and C in + * shared memory fields and calculates C = A * B. + * + * After calculation, it checks the result for correctness, compares execution + * time between serial calculation and shared memory parallelization and prints + * statistics about the different cores' access to shared pages. + * + * You can configure different SVM release consistency models: Set the + * \#define-constant `SVM_TYPE` to either `SVM_LAZYRELEASE` or `SVM_STRONG`. + * The `GET_B(i, j)` macro can be configured to transpose the matrix rows and + * columns. + * + * - __SVM_BENCH__: A benchmark for two executing cores. + * + * At first some shared memory pages are allocated. The benchmark measures the + * time the SVM implementation needs for creating and moving these pages between + * the cores. + * + * You can configure different SVM release consistency models: Set the + * \#define-constant `SVM_TYPE` to either `SVM_LAZYRELEASE` or `SVM_STRONG`. + * + * - __MAIL_PING__: MetalSVM provides a mailbox system using the iRCCE library as + * a foundation for communication between the SCC-cores. In this benchmark the + * latency of intercore-pings is measured: This involves sending a a PING-message, + * an intercore-interrupt, and waiting for the answer. + * + * - __MAIL_NOISE__: A high number of messages is sent from all cores to all cores to + * generate noise on the on-die mesh. + * + * Latency is measured, but this noise can also be used to check performance of + * other applications under influence of noise. + * + * - __KERNEL_LAPLACE__: This application iterates over a shared memory field with + * the laplace differential equation solver. Execution time will be measured. + * + * You can configure different SVM release consistency models: Set the + * \#define-constant `SVM_TYPE` to either `SVM_LAZYRELEASE` or `SVM_STRONG`. + * + * Location: `apps/laplace.c` + * + * - __KERNEL_JACOBI__: A shared memory implementation of the jacobi matrix equation + * solver. This is an interesting SVM example application, because besides + * `svm_barrier()`, it also uses `svm_flush()` and `svm_invalidate()`. + * + * You can configure different SVM release consistency models: Set the + * \#define-constant `SVM_TYPE` to either `SVM_LAZYRELEASE` or `SVM_STRONG`. + * + * Location: `apps/jacobi.c` + * + * - __ECHO__: Starts a new system thread providing an echo service over network + * listening on port 7. + * + * Location: `apps/echo.c` + * + * - **NETIO**: Measures the network throughput between two cores on the on-die mesh + * for different packet sizes. + * + * This benchmark consists of 2 kernel space tasks. + * + * Task 1 is the TCP server listening on port 18767. It will be started on RCCE + * rank 2. As a reaction to commands from a client it will send/receive data and + * measure the bandwidth of the transmission. + * + * Task 2 is the TCP client started on RCCE rank 0. It connects to the server task + * and sends commands to send/receive data, doing the same performance measurements + * as the server task. + * + * If the kernel is not configured for the SCC (`CONFIG_ROCKCREEK`), only the + * server task will be started. The client has to be started manually from elsewhere + * in this case. + * + * A possibility to improve the performance is bypassing the socket interface. + * To do this, activate the \#define constant `USE_SOCKET_BYPASSING` in the same file + * to a value != 0. + * + * Location: `apps/netio.c` + * + * @subsection general_ks Generic + * + * - __CONSUMER_PRODUCER__: A typical producer-consumer scenario testing the + * semaphore mechanism. After some cycles of producing and consuming, messages are + * sent over the mailbox interface. + * + * - __FOO__: A primitive kernel task example printing 5 kernel messages every second. + * Can be started multiple times to test the scheduler. + * + * - __JOIN_TEST__: A task starts a new child task executing the `foo`-example and + * and quits after the child task has executed using the `wait()` function. + * + * - __PI__: Serial calculation of pi. + * + * - __MEASURE_CTX_SWITCH__: Measures the pure overhead ticks of a context switch + * between 2 kernel space tasks. + * + * Both tasks continuously write the current TSC count to a shared variable until + * they are preempted and print the tick count the last context switch took. + * + * + * @section general_us Generic User Space Applications + * + * Located in: `newlib/examples/` + * + * - __MMNIF_TEST__: Starts a Server task on the first RCCE rank and + * a client task on every other rank. The clients request an example string + * to print it afterwards, while the server keeps responding with this string. + * + * + * - __hello__: Prints all environment variables and command line parameters. + * Opens a test file, writes an example string to it, reads the same string + * out again and afterwards prints the first directory entry of the `/bin` + * directory. + * + * - __jacobi__: A usual jacobi matrix solver application. Measures its execution time. + * + * - __mshell__: The M(etalsvm)shell provides basic commands to navigate through + * the file system, print out files and start applications. + * + * - __rlogind__: Started after boot by default, the rlogin daemon listens to port 4711. + * + * It pipes stdin and stdout over network, making shell access over telnet possible. + * + * - __tests__: Initiates a fork, where the child task starts an instance of the + * `hello` application with custom environment variables and command line parameters. + * The parent process waits for the child process to exit. + * + * + */ + diff --git a/documentation/text/compilation.dox b/documentation/text/compilation.dox index c883820c..67ca221c 100644 --- a/documentation/text/compilation.dox +++ b/documentation/text/compilation.dox @@ -16,11 +16,10 @@ * * \verbatim$ git clone git://git.lfbs.rwth-aachen.de/metalsvm.git \endverbatim * - * If you are asked for a password you are not authorized to clone the repository. In this case you will need to get your public SSH key authorized. - * * @section compiling Compiling MetalSVM * - * To compile MetalSVM, you will need a proper Makefile and configuration. To use the example files, just do the following: + * To compile MetalSVM, you will need a proper Makefile and configuration. + * To use the example files, just do the following: * * \verbatim $ cd MetalSVM @@ -28,8 +27,10 @@ $ cp Makefile.example Makefile $ (cd include/metalsvm; cp config.h.example config.h) \endverbatim * * The standard configuration works on usual PC hardware configurations as well as in emulators. + * There are also preconfigured example configs for the Intel SCC: `Makefile.scc` and `config.h.scc`. * - * Compiler settings can be edited in the Makefile, while the kernel configuration can be found in the just copied configuration file. + * Compiler settings can be edited in the Makefile, while the kernel configuration can be + * found in the configuration header file. * * @section runqemu Running MetalSVM in Qemu * @@ -41,19 +42,12 @@ $ (cd include/metalsvm; cp config.h.example config.h) \endverbatim * * @section runscc Running MetalSVM on the Intel SCC * - * -# Intel recommends to use their cross-compiler for generating code which is guaranteed to be SCC-compatible. Just set the environment variables with the following command: - * \verbatim$ . /opt/compilerSetupFiles/crosscompile.sh \endverbatim - * -# The Makefile needs to be adapted to actually use the cross compiler. - * Just uncomment two lines like seen here: - * \code -# Set your own cross compiler tool chain prefix here -CROSSCOMPREFIX= - -# Uncomment both lines if compiling for the SCC! -CROSSCOMPREFIX=i386-unknown-linux-gnu- -STACKPROT=\endcode - * -# Another important change in the Makefile is disabling the "-fno-stack-protector" option. It occurs several times. - * -# The SCC requires a special configuration for the MetalSVM kernel: + * -# Although Intel provides a special older GCC version for compiling code for the Intel SCC, + * the MetalSVM project switched to the current standard GCC. You don't need to source + * the cross compiler script which might be installed on your MCPC. + * -# An important change in the Makefile is disabling the "-fno-stack-protector" option. It occurs several times. This has already been done for you if you use `Makefile.scc`. + * -# The SCC requires a special configuration for the MetalSVM kernel (Already been done + * if you use `config.h.scc`): * \code //#define CONFIG_PCI //#define CONFIG_VGA @@ -78,6 +72,7 @@ STACKPROT=\endcode * \verbatim $ cd tools $ make SCC \endverbatim +* * -# The \c obj directory was just created, containing the MetalSVM kernel image. It can be loaded into the SCC's memory using \verbatim$ sccBoot -g obj \endverbatim * -# The default configuration lets MetalSVM run only on core 0. Its reset pin needs to be released: * \verbatim$ sccReset -r 0x00 \endverbatim @@ -90,9 +85,10 @@ $ make SCC \endverbatim * -# Build the kernel like described above (items 1-7) and change to the \c tools directory. * -# Now the file \c metalsvm.mt can be edited, depending on how many cores you want MetalSVM running. * Just remove the cores which shall be unaffected. Having a slim \c metalsvm.tm accelerates the build procedure. - * -# The final image must be generated then with \code$ make SCC\endcode + * -# The final image must be generated then with \code$ make SCC CORENUM=48\endcode + * where `CORENUM` is set to the actual number of cores which shall work together later. * -# A directory \c obj was created, containing the final MetalSVM Image. This image can now be loaded with the following command: \code$ sccBoot -g obj\endcode - * -# Everything has been placed in the cores' memory. To release the reset pins of the corresponding cores, type \code$ sccReset -r 0x00 0x01\endcode + * -# Everything has been placed in the cores' memory. To release the reset pins of the corresponding cores, type \code$ sccReset -r 0 1 2 3 ...\endcode * * @section msvmuart Enabling UART support * diff --git a/documentation/text/config.dox b/documentation/text/config.dox index e4e80343..b8246581 100644 --- a/documentation/text/config.dox +++ b/documentation/text/config.dox @@ -1,12 +1,14 @@ /** * @file config.dox - * @page config The MetalSVM feature configuration file + * @page config MetalSVM feature configuration files * - * @section conf MetalSVM's configuration file + * @section main_config MetalSVM's main configuration file * - * MetalSVM's configuration parameters and some features can be configured/activated in the central configuration file located at \c include/metalsvm/config.h. + * MetalSVM's configuration parameters and some features can be configured/activated + * in the central configuration file located at \c include/metalsvm/config.h. * - * The \c config.h is a usual C-header file and the configuration items are usual C preprocessor-definitions like the following: + * The `config.h` is a usual C header file and the configuration items are usual + * C preprocessor-definitions like the following: * \code #define CONFIGURATION_PARAMETER 123value /* A parameter with a value */ #define FEATURE_A /* An activated feature */ @@ -14,5 +16,53 @@ * * Just like the example suggests, features are deactivated by commenting them out. * + * If you boot MetalSVM on the Intel SCC, you need to \b deactivate `CONFIG_PCI`, + * `CONFIG_VGA`, `CONFIG_KEYBOARD`, and `CONFIG_MULTIBOOT` and + * \b activate `CONFIG_ROCKCREEK`. Set `CACHE_LINE` to 32.\n + * Activate `CONFIG_UART` if you are going to use software-UART and deactivate it if + * not, to avoid unnecessary traffic. + * + * @section lwip_config LwIP configuration flags + * + * The networking subsystem, based on LwIP, can of course be influenced by various + * feature flags. + * + * MetalSVM overrides various standard settings in `lwip/src/include/lwipopts.h`. + * + * If you chose `CONFIG_ROCKCREEK`, this leads to deactivation of `LWIP_DHCP`. + * + * If you chose `CONFIG_TICKLESS`, `NO_SYS` will be activated and the following + * are deactivated: `LWIP_SOCKET`, `LWIP_NETCON`, `LWIP_NETIF_API`. + * + * Another interesting feature is `LWIP_CHECKSUM_ON_COPY`. Deactivating it leads + * to higher network throughput for on-die communication. + * + * See LwIP documentation for more specific information about the individual effects of + * manipulating the LwIP configuration flags/values. + * + * @section mmnif_config MMNIF configuration flags + * Several flags in the file `drivers/net/mmnif.c` file influence the memory + * mapped network interface's performance: + * + * - `USE_CACHE`: activates the cache for the memory mapped buffer region. + * This improves the performance. + * - `USE_MPB`: If activated, the buffer will be mapped onto the SCC's special MPB, + * which improves the performance drastically. + * + * @section svm_config SVM configuration flags + * + * Although the choice between different shared memory release consistency models + * is configured in the application code, there are 2 flags which influence the SVM + * implementation. These are located in `arch/x86/mm/svm.c`: + * + * - `USE_PERFCOUNTERS`: Performance counters will help evaluating the performance + * of the SVM implementation within the kernel. Deactivate to omit overhead. + * + * - `USE_RESP_MAIL`: Whenever a core requests access to a page it is not the owner + * of, it sends an interrupt to the owner. The requesting core will then wait for the mail + * indicating that it has become the new owner of the particular page, spinning on its mailbox. + * When `USE_RESP_MAIL` is activated, other interrupts will be deactivated until the response + * has arrived. + * * */ diff --git a/documentation/text/tasks.dox b/documentation/text/tasks.dox index 835068ea..1bf62af4 100644 --- a/documentation/text/tasks.dox +++ b/documentation/text/tasks.dox @@ -108,7 +108,7 @@ static int foo(void* arg) * \c make in the project directory. * * The initrd building scripts include every file within the \c newlib/examples/ - * directory which is marked as \b execuable. Do not forget this if you use your + * directory which is marked as \b executable. Do not forget this if you use your * own build scripts! * * After providing your own executable for the system within the initial ramdisk, diff --git a/newlib/examples/hello.c b/newlib/examples/hello.c index 866da42a..8ef0d79d 100644 --- a/newlib/examples/hello.c +++ b/newlib/examples/hello.c @@ -29,6 +29,8 @@ #define NR_OPEN 10 #define FS_INIT { [0 ... NR_OPEN-1] = {NULL, 0, 0} } +#define TESTSTR "hello in new file '/bin/test.txt'" + int main(int argc, char** argv) { int i, testfile; @@ -43,25 +45,31 @@ int main(int argc, char** argv) teststr = malloc(sizeof(char)*100); if (!teststr) - return EFAULT; + exit(1); testfile = open("/bin/test.txt", O_CREAT | O_EXCL, "wr"); - if (testfile < 1) - printf("error"); - write(testfile, "hello in new file '/bin/test.txt'", 34); + if (testfile < 1) { + printf("error: Was not able to open /bin/test.txt\n"); + exit(1); + } + write(testfile, TESTSTR, 34); lseek(testfile, 0, SEEK_SET); read(testfile, teststr, 100); close(testfile); + printf("read from new file: %s\n", teststr); + + if (strcmp(teststr, TESTSTR)) + exit(1); + testdir = opendir("/bin/"); - if (testdir < 1) - printf("error"); + if (testdir < 1) { + printf("error: Was not able to open /bin directory"); + exit(1); + } testdirent = readdir(testdir); printf("1. Dirent: %s", testdirent->d_name); closedir(testdir); - - - printf("read from new file: %s\n", teststr); return errno; } diff --git a/newlib/examples/jacobi.c b/newlib/examples/jacobi.c index 968360e4..e9ab0a84 100644 --- a/newlib/examples/jacobi.c +++ b/newlib/examples/jacobi.c @@ -178,8 +178,10 @@ int main(int argc, char **argv) if (max < error) max = error; - if (error > 0.01f) - printf("Result is on position %d wrong (%f != 1.0)\n", i, X[i]); + if (error > 0.01f) { + printf("Result is on position %d wrong (%f != 1.0)\n", i, X[i]); + exit(1); + } } printf("maximal error is %f\n", max);