Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756330Ab0AMUYw (ORCPT ); Wed, 13 Jan 2010 15:24:52 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756255Ab0AMUYv (ORCPT ); Wed, 13 Jan 2010 15:24:51 -0500 Received: from lon1-post-3.mail.demon.net ([195.173.77.150]:49574 "EHLO lon1-post-3.mail.demon.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756120Ab0AMUYv (ORCPT ); Wed, 13 Jan 2010 15:24:51 -0500 Date: Wed, 13 Jan 2010 20:23:28 +0000 From: Phillip Lougher To: linux-fsdevel@vger.kernel.org, linux-next@vger.kernel.org, linux-kernel@vger.kernel.org Cc: phillip.lougher@gmail.com Subject: [PATCH V3 2/2] lzma: make lzma reentrant Message-ID: <4b4e2bc0.YCBOD8ZeQJ4fOOyb%phillip@lougher.demon.co.uk> User-Agent: Heirloom mailx 12.4 7/29/08 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 12147 Lines: 368 The error function pointer used by lzma is global (file scope) which prevents it being used concurrently. This patch removes the global error pointer use, and instead passes it to all functions that need it. The error function pointer is still used by bunzip2, inflate and unlzo. This patch moves the definition into the separate bunzip2, inflate and unlzo header files. This prevents gcc from complaining about an unused definition compiling lzma. Signed-off-by: Phillip Lougher --- include/linux/decompress/bunzip2_mm.h | 1 + include/linux/decompress/inflate_mm.h | 1 + include/linux/decompress/mm.h | 1 - include/linux/decompress/unlzo_mm.h | 1 + lib/decompress_unlzma.c | 82 +++++++++++++++++---------------- 5 files changed, 45 insertions(+), 41 deletions(-) diff --git a/include/linux/decompress/bunzip2_mm.h b/include/linux/decompress/bunzip2_mm.h index cac6fef..863efd0 100644 --- a/include/linux/decompress/bunzip2_mm.h +++ b/include/linux/decompress/bunzip2_mm.h @@ -7,6 +7,7 @@ #else /* Compile for initramfs/initrd code only */ #define INIT __init +static void(*error)(char *m); #endif #endif diff --git a/include/linux/decompress/inflate_mm.h b/include/linux/decompress/inflate_mm.h index ca4a2ae..87a742b 100644 --- a/include/linux/decompress/inflate_mm.h +++ b/include/linux/decompress/inflate_mm.h @@ -7,6 +7,7 @@ #else /* Compile for initramfs/initrd code only */ #define INIT __init +static void(*error)(char *m); #endif #endif diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h index 93dd574..44f6e14 100644 --- a/include/linux/decompress/mm.h +++ b/include/linux/decompress/mm.h @@ -72,7 +72,6 @@ static void free(void *where) #define large_malloc(a) vmalloc(a) #define large_free(a) vfree(a) -static void(*error)(char *m); #define set_error_fn(x) error = x; #define STATIC diff --git a/include/linux/decompress/unlzo_mm.h b/include/linux/decompress/unlzo_mm.h index e3f1573..27fe0ab 100644 --- a/include/linux/decompress/unlzo_mm.h +++ b/include/linux/decompress/unlzo_mm.h @@ -7,6 +7,7 @@ #else /* Compile for initramfs/initrd code only */ #define INIT __init +static void(*error)(char *m); #endif #endif diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c index a614b26..3e85763 100644 --- a/lib/decompress_unlzma.c +++ b/lib/decompress_unlzma.c @@ -89,7 +89,7 @@ static int nofill(void *buffer, unsigned int len) } /* Called twice: once at startup and once in rc_normalize() */ -static void INIT rc_read(struct rc *rc) +static void INIT rc_read(struct rc *rc, void(*error)(char *x)) { rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE); if (rc->buffer_size <= 0) @@ -116,13 +116,13 @@ static inline void INIT rc_init(struct rc *rc, rc->range = 0xFFFFFFFF; } -static inline void INIT rc_init_code(struct rc *rc) +static inline void INIT rc_init_code(struct rc *rc, void(*error)(char *x)) { int i; for (i = 0; i < 5; i++) { if (rc->ptr >= rc->buffer_end) - rc_read(rc); + rc_read(rc, error); rc->code = (rc->code << 8) | *rc->ptr++; } } @@ -135,32 +135,33 @@ static inline void INIT rc_free(struct rc *rc) } /* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */ -static void INIT rc_do_normalize(struct rc *rc) +static void INIT rc_do_normalize(struct rc *rc, void(*error)(char *x)) { if (rc->ptr >= rc->buffer_end) - rc_read(rc); + rc_read(rc, error); rc->range <<= 8; rc->code = (rc->code << 8) | *rc->ptr++; } -static inline void INIT rc_normalize(struct rc *rc) +static inline void INIT rc_normalize(struct rc *rc, void(*error)(char *x)) { if (rc->range < (1 << RC_TOP_BITS)) - rc_do_normalize(rc); + rc_do_normalize(rc, error); } /* Called 9 times */ /* Why rc_is_bit_0_helper exists? *Because we want to always expose (rc->code < rc->bound) to optimizer */ -static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p) +static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p, + void (*error)(char *x)) { - rc_normalize(rc); + rc_normalize(rc, error); rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS); return rc->bound; } -static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p) +static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p, void(*error)(char *x)) { - uint32_t t = rc_is_bit_0_helper(rc, p); + uint32_t t = rc_is_bit_0_helper(rc, p, error); return rc->code < t; } @@ -178,9 +179,9 @@ static inline void rc_update_bit_1(struct rc *rc, uint16_t *p) } /* Called 4 times in unlzma loop */ -static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol) +static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol, void(*error)(char *x)) { - if (rc_is_bit_0(rc, p)) { + if (rc_is_bit_0(rc, p, error)) { rc_update_bit_0(rc, p); *symbol *= 2; return 0; @@ -192,9 +193,9 @@ static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol) } /* Called once */ -static inline int INIT rc_direct_bit(struct rc *rc) +static inline int INIT rc_direct_bit(struct rc *rc , void(*error)(char *x)) { - rc_normalize(rc); + rc_normalize(rc, error); rc->range >>= 1; if (rc->code >= rc->range) { rc->code -= rc->range; @@ -205,13 +206,14 @@ static inline int INIT rc_direct_bit(struct rc *rc) /* Called twice */ static inline void INIT -rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol) +rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol, + void(*error)(char *x)) { int i = num_levels; *symbol = 1; while (i--) - rc_get_bit(rc, p + *symbol, symbol); + rc_get_bit(rc, p + *symbol, symbol, error); *symbol -= 1 << num_levels; } @@ -348,7 +350,8 @@ static inline void INIT copy_bytes(struct writer *wr, static inline void INIT process_bit0(struct writer *wr, struct rc *rc, struct cstate *cst, uint16_t *p, int pos_state, uint16_t *prob, - int lc, uint32_t literal_pos_mask) { + int lc, uint32_t literal_pos_mask, + void(*error)(char *x)) { int mi = 1; rc_update_bit_0(rc, prob); prob = (p + LZMA_LITERAL + @@ -366,7 +369,7 @@ static inline void INIT process_bit0(struct writer *wr, struct rc *rc, match_byte <<= 1; bit = match_byte & 0x100; prob_lit = prob + 0x100 + bit + mi; - if (rc_get_bit(rc, prob_lit, &mi)) { + if (rc_get_bit(rc, prob_lit, &mi, error)) { if (!bit) break; } else { @@ -377,7 +380,7 @@ static inline void INIT process_bit0(struct writer *wr, struct rc *rc, } while (mi < 0x100) { uint16_t *prob_lit = prob + mi; - rc_get_bit(rc, prob_lit, &mi); + rc_get_bit(rc, prob_lit, &mi, error); } write_byte(wr, mi); if (cst->state < 4) @@ -390,7 +393,8 @@ static inline void INIT process_bit0(struct writer *wr, struct rc *rc, static inline void INIT process_bit1(struct writer *wr, struct rc *rc, struct cstate *cst, uint16_t *p, - int pos_state, uint16_t *prob) { + int pos_state, uint16_t *prob, + void(*error)(char *x)) { int offset; uint16_t *prob_len; int num_bits; @@ -398,7 +402,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, rc_update_bit_1(rc, prob); prob = p + LZMA_IS_REP + cst->state; - if (rc_is_bit_0(rc, prob)) { + if (rc_is_bit_0(rc, prob, error)) { rc_update_bit_0(rc, prob); cst->rep3 = cst->rep2; cst->rep2 = cst->rep1; @@ -408,13 +412,13 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, } else { rc_update_bit_1(rc, prob); prob = p + LZMA_IS_REP_G0 + cst->state; - if (rc_is_bit_0(rc, prob)) { + if (rc_is_bit_0(rc, prob, error)) { rc_update_bit_0(rc, prob); prob = (p + LZMA_IS_REP_0_LONG + (cst->state << LZMA_NUM_POS_BITS_MAX) + pos_state); - if (rc_is_bit_0(rc, prob)) { + if (rc_is_bit_0(rc, prob, error)) { rc_update_bit_0(rc, prob); cst->state = cst->state < LZMA_NUM_LIT_STATES ? @@ -429,13 +433,13 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, rc_update_bit_1(rc, prob); prob = p + LZMA_IS_REP_G1 + cst->state; - if (rc_is_bit_0(rc, prob)) { + if (rc_is_bit_0(rc, prob, error)) { rc_update_bit_0(rc, prob); distance = cst->rep1; } else { rc_update_bit_1(rc, prob); prob = p + LZMA_IS_REP_G2 + cst->state; - if (rc_is_bit_0(rc, prob)) { + if (rc_is_bit_0(rc, prob, error)) { rc_update_bit_0(rc, prob); distance = cst->rep2; } else { @@ -453,7 +457,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, } prob_len = prob + LZMA_LEN_CHOICE; - if (rc_is_bit_0(rc, prob_len)) { + if (rc_is_bit_0(rc, prob_len, error)) { rc_update_bit_0(rc, prob_len); prob_len = (prob + LZMA_LEN_LOW + (pos_state << @@ -463,7 +467,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, } else { rc_update_bit_1(rc, prob_len); prob_len = prob + LZMA_LEN_CHOICE_2; - if (rc_is_bit_0(rc, prob_len)) { + if (rc_is_bit_0(rc, prob_len, error)) { rc_update_bit_0(rc, prob_len); prob_len = (prob + LZMA_LEN_MID + (pos_state << @@ -479,7 +483,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, } } - rc_bit_tree_decode(rc, prob_len, num_bits, &len); + rc_bit_tree_decode(rc, prob_len, num_bits, &len, error); len += offset; if (cst->state < 4) { @@ -494,7 +498,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, << LZMA_NUM_POS_SLOT_BITS); rc_bit_tree_decode(rc, prob, LZMA_NUM_POS_SLOT_BITS, - &pos_slot); + &pos_slot, error); if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { int i, mi; num_bits = (pos_slot >> 1) - 1; @@ -507,7 +511,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, num_bits -= LZMA_NUM_ALIGN_BITS; while (num_bits--) cst->rep0 = (cst->rep0 << 1) | - rc_direct_bit(rc); + rc_direct_bit(rc, error); prob = p + LZMA_ALIGN; cst->rep0 <<= LZMA_NUM_ALIGN_BITS; num_bits = LZMA_NUM_ALIGN_BITS; @@ -515,7 +519,7 @@ static inline void INIT process_bit1(struct writer *wr, struct rc *rc, i = 1; mi = 1; while (num_bits--) { - if (rc_get_bit(rc, prob + mi, &mi)) + if (rc_get_bit(rc, prob + mi, &mi, error)) cst->rep0 |= i; i <<= 1; } @@ -537,7 +541,7 @@ STATIC int INIT unlzma(unsigned char *buf, int in_len, int(*flush)(void*, unsigned int), unsigned char *output, int *posp, - void(*error_fn)(char *x) + void(*error)(char *x) ) { struct lzma_header header; @@ -553,8 +557,6 @@ STATIC int INIT unlzma(unsigned char *buf, int in_len, unsigned char *inbuf; int ret = -1; - set_error_fn(error_fn); - if (buf) inbuf = buf; else @@ -577,7 +579,7 @@ STATIC int INIT unlzma(unsigned char *buf, int in_len, for (i = 0; i < sizeof(header); i++) { if (rc.ptr >= rc.buffer_end) - rc_read(&rc); + rc_read(&rc, error); ((unsigned char *)&header)[i] = *rc.ptr++; } @@ -622,17 +624,17 @@ STATIC int INIT unlzma(unsigned char *buf, int in_len, for (i = 0; i < num_probs; i++) p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; - rc_init_code(&rc); + rc_init_code(&rc, error); while (get_pos(&wr) < header.dst_size) { int pos_state = get_pos(&wr) & pos_state_mask; uint16_t *prob = p + LZMA_IS_MATCH + (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state; - if (rc_is_bit_0(&rc, prob)) + if (rc_is_bit_0(&rc, prob, error)) process_bit0(&wr, &rc, &cst, p, pos_state, prob, - lc, literal_pos_mask); + lc, literal_pos_mask, error); else { - process_bit1(&wr, &rc, &cst, p, pos_state, prob); + process_bit1(&wr, &rc, &cst, p, pos_state, prob, error); if (cst.rep0 == 0) break; } -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/