diff --git a/system/lzf/Kconfig b/system/lzf/Kconfig index e872fb98b..c482d5d55 100644 --- a/system/lzf/Kconfig +++ b/system/lzf/Kconfig @@ -12,6 +12,23 @@ config SYSTEM_LZF if SYSTEM_LZF +config SYSTEM_LZF_BLOG + int "Log2 of block size" + default 10 + range 9 12 + ---help--- + This example uses two buffers of size a little more than + (1 << CONFIG_SYSTEM_LZF_BLOG) to compress and decompress data in + chunks. Slightly better compression should be obtainable with larger + chunks. + + NOTE: This is a static memory allocation and will take add a little + more than 2 * (1 << CONFIG_SYSTEM_LZF_BLOG) bytes to the size of the + .bss section used by the program. + + NOTE: This represents a maximum blocksize. The use may select a + smaller blocksize using the 'lzf -b' option. + config SYSTEM_LZF_PROGNAME string "Program name" default "lzf" diff --git a/system/lzf/lzf_main.c b/system/lzf/lzf_main.c index b5d8a23d4..ca3135b99 100644 --- a/system/lzf/lzf_main.c +++ b/system/lzf/lzf_main.c @@ -1,5 +1,5 @@ /**************************************************************************** - * apps/exmaples/lzf/lxf_main.c + * apps/exmaples/lzf/lzf_main.c * * Copyright (c) 2006 Stefan Traby * @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -50,13 +51,17 @@ * Pre-processor Definitions ****************************************************************************/ -#define BLOCKSIZE (512 - 1) +#define BLOCKSIZE ((1 << CONFIG_SYSTEM_LZF_BLOG) - 1) #define MAX_BLOCKSIZE BLOCKSIZE /**************************************************************************** * Private Data ****************************************************************************/ +#ifndef CONFIG_BUILD_KERNEL +static sem_t g_exclsem = SEM_INITIALIZER(1); +#endif + static off_t g_nread; static off_t g_nwritten; @@ -64,22 +69,26 @@ static FAR const char *g_imagename; static enum { COMPRESS, UNCOMPRESS } g_mode; static bool g_verbose; static bool g_force; -static long blocksize; +static unsigned long g_blocksize; static lzf_state_t g_htab; - -static FAR const char *opt = - "-c compress\n" - "-d decompress\n" - "-f force overwrite of output file\n" - "-h give this help\n" - "-v verbose mode\n" - "-b # set blocksize\n" - "\n"; +static uint8_t g_buf1[MAX_BLOCKSIZE + LZF_MAX_HDR_SIZE + 16]; +static uint8_t g_buf2[MAX_BLOCKSIZE + LZF_MAX_HDR_SIZE + 16]; /**************************************************************************** * Private Functions ****************************************************************************/ +#ifndef CONFIG_BUILD_KERNEL +static void lzf_exit(int exitcode) noreturn_function; +static void lzf_exit(int exitcode) +{ + (void)sem_post(&g_exclsem); + exit(exitcode); +} +#else +# define lzf_exit(c) exit(c) +#endif + static void usage(int ret) { fprintf(stderr, "\n" @@ -87,11 +96,16 @@ static void usage(int ret) "uses liblzf written by Marc Lehmann You can find more info at\n" "http://liblzf.plan9.de/\n" "\n" - "usage: lzf [-dufhvb] [file ...]\n" - "\n%s", - opt); + "usage: lzf [-dufhvb] [file ...]\n\n" + "-c Compress\n" + "-d Decompress\n" + "-f Force overwrite of output file\n" + "-h Give this help\n" + "-v Verbose mode\n" + "-b # Set blocksize (max %lu)\n" + "\n", (unsigned long)MAX_BLOCKSIZE); - exit(ret); + lzf_exit(ret); } static inline ssize_t rread(int fd, FAR void *buf, size_t len) @@ -153,14 +167,12 @@ static int compress_fd(int from, int to) { ssize_t us; ssize_t len; - uint8_t buf1[MAX_BLOCKSIZE + LZF_MAX_HDR_SIZE + 16]; - uint8_t buf2[MAX_BLOCKSIZE + LZF_MAX_HDR_SIZE + 16]; uint8_t *header; g_nread = g_nwritten = 0; - while ((us = rread(from, &buf1[LZF_MAX_HDR_SIZE], blocksize)) > 0) + while ((us = rread(from, &g_buf1[LZF_MAX_HDR_SIZE], g_blocksize)) > 0) { - len = lzf_compress(&buf1[LZF_MAX_HDR_SIZE], us, &buf2[LZF_MAX_HDR_SIZE], + len = lzf_compress(&g_buf1[LZF_MAX_HDR_SIZE], us, &g_buf2[LZF_MAX_HDR_SIZE], us > 4 ? us - 4 : us, g_htab, &header); if (wwrite(to, header, len) == -1) { @@ -174,8 +186,6 @@ static int compress_fd(int from, int to) static int uncompress_fd(int from, int to) { uint8_t header[LZF_MAX_HDR_SIZE]; - uint8_t buf1[MAX_BLOCKSIZE + LZF_MAX_HDR_SIZE + 16]; - uint8_t buf2[MAX_BLOCKSIZE + LZF_MAX_HDR_SIZE + 16]; FAR uint8_t *p; int l; int rd; @@ -238,7 +248,7 @@ static int uncompress_fd(int from, int to) if (l > 0) { - memcpy(buf1, p, l); + memcpy(g_buf1, p, l); } if (l > bytes) @@ -247,7 +257,7 @@ static int uncompress_fd(int from, int to) memmove(header, &p[bytes], over); } - p = &buf1[l]; + p = &g_buf1[l]; rd = bytes - l; if (rd > 0) { @@ -259,21 +269,21 @@ static int uncompress_fd(int from, int to) if (cs == -1) { - if (wwrite (to, buf1, us)) + if (wwrite (to, g_buf1, us)) { return -1; } } else { - if (lzf_decompress(buf1, cs, buf2, us) != us) + if (lzf_decompress(g_buf1, cs, g_buf2, us) != us) { fprintf(stderr, "%s: decompress: invalid stream - data corrupted\n", g_imagename); return -1; } - if (wwrite(to, buf2, us)) + if (wwrite(to, g_buf2, us)) { return -1; } @@ -433,12 +443,35 @@ int lzf_main(int argc, FAR char *argv[]) int optc; int ret = 0; +#ifndef CONFIG_BUILD_KERNEL + /* Get exclusive access to the global variables. Global variables are + * used because the hash table and buffers are too large to allocate on + * the embedded stack. But the use of global variables has the downside + * or forcing serialization of this logic in order to work in a multi- + * tasking environment. + * + * REVISIT: An alternative would be to pack all of the globals into a + * structure and allocate a per-thread instance of that structure here. + * + * NOTE: This applies only in the FLAT and PROTECTED build modes. In the + * KERNEL build mode, this will be a separate process with its own private + * global variables. + */ + + ret = sem_wait(&g_exclsem); + if (ret < 0) + { + fprintf(stderr, "sem_wait failed: %d\n", errno); + exit(1); + } +#endif + /* Set defaults. */ - g_mode = COMPRESS; - g_verbose = false; - g_force = 0; - blocksize = BLOCKSIZE; + g_mode = COMPRESS; + g_verbose = false; + g_force = 0; + g_blocksize = BLOCKSIZE; #ifndef CONFIG_DISABLE_ENVIRON /* Block size may be specified as an environment variable */ @@ -446,10 +479,10 @@ int lzf_main(int argc, FAR char *argv[]) p = getenv("LZF_BLOCKSIZE"); if (p) { - blocksize = strtoul(p, 0, 0); - if (!blocksize || blocksize > MAX_BLOCKSIZE) + g_blocksize = strtoul(p, 0, 0); + if (g_blocksize == 0 || g_blocksize > MAX_BLOCKSIZE) { - blocksize = BLOCKSIZE; + g_blocksize = BLOCKSIZE; } } #endif @@ -486,10 +519,10 @@ int lzf_main(int argc, FAR char *argv[]) break; case 'b': - blocksize = strtoul(optarg, 0, 0); - if (!blocksize || blocksize > MAX_BLOCKSIZE) + g_blocksize = strtoul(optarg, 0, 0); + if (g_blocksize == 0 || g_blocksize > MAX_BLOCKSIZE) { - blocksize = BLOCKSIZE; + g_blocksize = BLOCKSIZE; } break; @@ -511,14 +544,14 @@ int lzf_main(int argc, FAR char *argv[]) { fprintf(stderr, "%s: compressed data not read from a terminal. " "Use -f to force decompression.\n", g_imagename); - exit(1); + lzf_exit(1); } if (g_mode == COMPRESS && isatty(1)) { fprintf(stderr, "%s: compressed data not written to a terminal. " "Use -f to force compression.\n", g_imagename); - exit(1); + lzf_exit(1); } } #endif @@ -532,7 +565,7 @@ int lzf_main(int argc, FAR char *argv[]) ret = uncompress_fd(0, 1); } - exit(ret ? 1 : 0); + lzf_exit(ret ? 1 : 0); } while (optind < argc) @@ -540,5 +573,5 @@ int lzf_main(int argc, FAR char *argv[]) ret |= run_file(argv[optind++]); } - exit(ret ? 1 : 0); + lzf_exit(ret ? 1 : 0); }