From a51fc20e704588fadd285cf939f080df4552694b Mon Sep 17 00:00:00 2001
From: Phillip Lougher <phillip@lougher.demon.co.uk>
Date: Mon, 11 Jan 2010 16:45:50 +0000
Subject: [PATCH] lzma: make lzma reentrant

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 <phillip@lougher.demon.co.uk>
---
 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 f3f6526..df8b8b5 100644
--- a/include/linux/decompress/mm.h
+++ b/include/linux/decompress/mm.h
@@ -82,7 +82,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.7.3

