Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933586AbZLGIiD (ORCPT ); Mon, 7 Dec 2009 03:38:03 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1759244AbZLGIiA (ORCPT ); Mon, 7 Dec 2009 03:38:00 -0500 Received: from anchor-post-3.mail.demon.net ([195.173.77.134]:65204 "EHLO anchor-post-3.mail.demon.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759084AbZLGIhn (ORCPT ); Mon, 7 Dec 2009 03:37:43 -0500 To: akpm@linux-foundation.org, linux-embedded@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, phillip.lougher@gmail.com, tim.bird@am.sony.com Subject: [PATCH 9/9] lzma: make lzma reentrant Message-Id: From: Phillip Lougher Date: Mon, 07 Dec 2009 08:37:49 +0000 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 11738 Lines: 356 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 bzip2 and inflate. This patch moves the definition into the separate bzip2/inflate 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 - lib/decompress_unlzma.c | 82 +++++++++++++++++---------------- 4 files changed, 44 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 80f5ba4..32651e4 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/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/