1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13
14 /* $Id: gxbcache.c 8022 2007-06-05 22:23:38Z giles $ */
15 /* Bitmap cache implementation */
16 #include "memory_.h"
17 #include "gx.h"
18 #include "gsmdebug.h"
19 #include "gxbcache.h"
20
21 /* ------ Entire cache ------ */
22
23 /* Initialize a cache. The caller must allocate and initialize */
24 /* the first chunk. */
25 void
gx_bits_cache_init(gx_bits_cache * bc,gx_bits_cache_chunk * bck)26 gx_bits_cache_init(gx_bits_cache * bc, gx_bits_cache_chunk * bck)
27 {
28 bck->next = bck;
29 bc->chunks = bck;
30 bc->cnext = 0;
31 bc->bsize = 0;
32 bc->csize = 0;
33 }
34
35 /* ------ Chunks ------ */
36
37 /* Initialize a chunk. The caller must allocate it and its data. */
38 void
gx_bits_cache_chunk_init(gx_bits_cache_chunk * bck,byte * data,uint size)39 gx_bits_cache_chunk_init(gx_bits_cache_chunk * bck, byte * data, uint size)
40 {
41 bck->next = 0;
42 bck->data = data;
43 bck->size = size;
44 bck->allocated = 0;
45 if (data != 0) {
46 gx_cached_bits_head *cbh = (gx_cached_bits_head *) data;
47
48 cbh->size = size;
49 cb_head_set_free(cbh);
50 }
51 }
52
53 /* ------ Individual entries ------ */
54
55 /* Attempt to allocate an entry. If successful, set *pcbh and return 0. */
56 /* If there isn't enough room, set *pcbh to an entry requiring freeing, */
57 /* or to 0 if we are at the end of the chunk, and return -1. */
58 int
gx_bits_cache_alloc(gx_bits_cache * bc,ulong lsize,gx_cached_bits_head ** pcbh)59 gx_bits_cache_alloc(gx_bits_cache * bc, ulong lsize, gx_cached_bits_head ** pcbh)
60 {
61 #define ssize ((uint)lsize)
62 ulong lsize1 = lsize + sizeof(gx_cached_bits_head);
63
64 #define ssize1 ((uint)lsize1)
65 uint cnext = bc->cnext;
66 gx_bits_cache_chunk *bck = bc->chunks;
67 uint left = bck->size - cnext;
68 gx_cached_bits_head *cbh;
69 gx_cached_bits_head *cbh_next;
70 uint fsize = 0;
71
72 if (lsize1 > bck->size - cnext && lsize != left) { /* Not enough room to allocate in this chunk. */
73 *pcbh = 0;
74 return -1;
75 }
76 /* Look for and/or free enough space. */
77 cbh = cbh_next = (gx_cached_bits_head *) (bck->data + cnext);
78 while (fsize < ssize1 && fsize != ssize) {
79 if (!cb_head_is_free(cbh_next)) { /* Ask the caller to free the entry. */
80 if (fsize)
81 cbh->size = fsize;
82 *pcbh = cbh_next;
83 return -1;
84 }
85 fsize += cbh_next->size;
86 if_debug2('K', "[K]merging free bits 0x%lx(%u)\n",
87 (ulong) cbh_next, cbh_next->size);
88 cbh_next = (gx_cached_bits_head *) ((byte *) cbh + fsize);
89 }
90 if (fsize > ssize) { /* fsize >= ssize1 */
91 cbh_next = (gx_cached_bits_head *) ((byte *) cbh + ssize);
92 cbh_next->size = fsize - ssize;
93 cb_head_set_free(cbh_next);
94 if_debug2('K', "[K]shortening bits 0x%lx by %u (initial)\n",
95 (ulong) cbh, fsize - ssize);
96 }
97 gs_alloc_fill(cbh, gs_alloc_fill_block, ssize);
98 cbh->size = ssize;
99 bc->bsize += ssize;
100 bc->csize++;
101 bc->cnext += ssize;
102 bck->allocated += ssize;
103 *pcbh = cbh;
104 return 0;
105 #undef ssize
106 #undef ssize1
107 }
108
109 /* Shorten an entry by a given amount. */
110 void
gx_bits_cache_shorten(gx_bits_cache * bc,gx_cached_bits_head * cbh,uint diff,gx_bits_cache_chunk * bck)111 gx_bits_cache_shorten(gx_bits_cache * bc, gx_cached_bits_head * cbh,
112 uint diff, gx_bits_cache_chunk * bck)
113 {
114 gx_cached_bits_head *next;
115
116 if ((byte *) cbh + cbh->size == bck->data + bc->cnext &&
117 bck == bc->chunks
118 )
119 bc->cnext -= diff;
120 bc->bsize -= diff;
121 bck->allocated -= diff;
122 cbh->size -= diff;
123 next = (gx_cached_bits_head *) ((byte *) cbh + cbh->size);
124 cb_head_set_free(next);
125 next->size = diff;
126 }
127
128 /* Free an entry. The caller is responsible for removing the entry */
129 /* from any other structures (like a hash table). */
130 void
gx_bits_cache_free(gx_bits_cache * bc,gx_cached_bits_head * cbh,gx_bits_cache_chunk * bck)131 gx_bits_cache_free(gx_bits_cache * bc, gx_cached_bits_head * cbh,
132 gx_bits_cache_chunk * bck)
133 {
134 uint size = cbh->size;
135
136 bc->csize--;
137 bc->bsize -= size;
138 bck->allocated -= size;
139 gs_alloc_fill(cbh, gs_alloc_fill_deleted, size);
140 cbh->size = size; /* gs_alloc_fill may have overwritten */
141 cb_head_set_free(cbh);
142 }
143