/[rdesktop]/sourceforge.net/trunk/rdesktop/cache.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/cache.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 726 by stargo, Sun Jun 27 18:53:08 2004 UTC revision 963 by astrand, Wed Aug 3 10:56:16 2005 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Cache routines     Cache routines
4     Copyright (C) Matthew Chapman 1999-2002     Copyright (C) Matthew Chapman 1999-2005
5         Copyright (C) Jeroen Meijer 2005
6    
7     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.     (at your option) any later version.
11      
12     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.     GNU General Public License for more details.
16      
17     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# Line 20  Line 21 
21    
22  #include "rdesktop.h"  #include "rdesktop.h"
23    
24    /* BITMAP CACHE */
25    extern int g_pstcache_fd[];
26    
27  #define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))  #define NUM_ELEMENTS(array) (sizeof(array) / sizeof(array[0]))
 #define TOUCH(id, idx) (g_bmpcache[id][idx].usage = ++g_stamp)  
28  #define IS_PERSISTENT(id) (g_pstcache_fd[id] > 0)  #define IS_PERSISTENT(id) (g_pstcache_fd[id] > 0)
29    #define TO_TOP -1
30    #define NOT_SET -1
31    #define IS_SET(idx) (idx >= 0)
32    
33  extern int g_pstcache_fd[];  /*
34     * TODO: Test for optimal value of BUMP_COUNT. TO_TOP gives lowest cpu utilisation but using
35     * a positive value will hopefully result in less frequently used bitmaps having a greater chance
36     * of being evicted from the cache, and therby reducing the need to load bitmaps from disk.
37     * (Jeroen)
38     */
39    #define BUMP_COUNT 40
40    
41    struct bmpcache_entry
42    {
43            HBITMAP bitmap;
44            sint16 previous;
45            sint16 next;
46    };
47    
48    static struct bmpcache_entry g_bmpcache[3][0xa00];
49    static HBITMAP g_volatile_bc[3];
50    
51    static int g_bmpcache_lru[3] = { NOT_SET, NOT_SET, NOT_SET };
52    static int g_bmpcache_mru[3] = { NOT_SET, NOT_SET, NOT_SET };
53    static int g_bmpcache_count[3];
54    
55    /* Setup the bitmap cache lru/mru linked list */
56    void
57    cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count)
58    {
59            int n = count, c = 0;
60            sint16 n_idx;
61    
62            /* find top, skip evicted bitmaps */
63            while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL);
64            if (n < 0)
65            {
66                    g_bmpcache_mru[id] = g_bmpcache_lru[id] = NOT_SET;
67                    return;
68            }
69    
70  uint32 g_stamp;          g_bmpcache_mru[id] = idx[n];
71  int g_num_bitmaps_in_memory[3];          g_bmpcache[id][idx[n]].next = NOT_SET;
72            n_idx = idx[n];
73            c++;
74    
75            /* link list */
76            while (n >= 0)
77            {
78                    /* skip evicted bitmaps */
79                    while (--n >= 0 && g_bmpcache[id][idx[n]].bitmap == NULL);
80    
81  /* BITMAP CACHE */                  if (n < 0)
82  static BMPCACHEENTRY g_bmpcache[3][0xa00];                          break;
83    
84                    g_bmpcache[id][n_idx].previous = idx[n];
85                    g_bmpcache[id][idx[n]].next = n_idx;
86                    n_idx = idx[n];
87                    c++;
88            }
89    
90            g_bmpcache[id][n_idx].previous = NOT_SET;
91            g_bmpcache_lru[id] = n_idx;
92    
93            if (c != g_bmpcache_count[id])
94            {
95                    error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c,
96                          g_bmpcache_count[id]);
97                    exit(1);
98            }
99    }
100    
101  /* Remove the least-recently used bitmap from the cache */  /* Move a bitmap to a new position in the linked list. */
102  void  void
103  cache_remove_lru_bitmap(uint8 cache_id)  cache_bump_bitmap(uint8 id, uint16 idx, int bump)
104  {  {
105          int i;          int p_idx, n_idx, n;
106          uint16 cache_idx = 0;  
107          uint32 m = (uint32)-1;          if (!IS_PERSISTENT(id))
108          BMPCACHEENTRY *pbce;                  return;
109    
110            if (g_bmpcache_mru[id] == idx)
111                    return;
112    
113            DEBUG_RDP5(("bump bitmap: id=%d, idx=%d, bump=%d\n", id, idx, bump));
114    
115            n_idx = g_bmpcache[id][idx].next;
116            p_idx = g_bmpcache[id][idx].previous;
117    
118          for (i = 0; i < NUM_ELEMENTS(g_bmpcache[cache_id]); i++)          if (IS_SET(n_idx))
119          {          {
120                  if (g_bmpcache[cache_id][i].bitmap && g_bmpcache[cache_id][i].usage < m)                  /* remove */
121                    --g_bmpcache_count[id];
122                    if (IS_SET(p_idx))
123                            g_bmpcache[id][p_idx].next = n_idx;
124                    else
125                            g_bmpcache_lru[id] = n_idx;
126                    if (IS_SET(n_idx))
127                            g_bmpcache[id][n_idx].previous = p_idx;
128                    else
129                            g_bmpcache_mru[id] = p_idx;
130            }
131            else
132            {
133                    p_idx = NOT_SET;
134                    n_idx = g_bmpcache_lru[id];
135            }
136    
137            if (bump >= 0)
138            {
139                    for (n = 0; n < bump && IS_SET(n_idx); n++)
140                  {                  {
141                          cache_idx = i;                          p_idx = n_idx;
142                          m = g_bmpcache[cache_id][i].usage;                          n_idx = g_bmpcache[id][p_idx].next;
143                  }                  }
144          }          }
145            else
146            {
147                    p_idx = g_bmpcache_mru[id];
148                    n_idx = NOT_SET;
149            }
150    
151            /* insert */
152            ++g_bmpcache_count[id];
153            g_bmpcache[id][idx].previous = p_idx;
154            g_bmpcache[id][idx].next = n_idx;
155    
156            if (p_idx >= 0)
157                    g_bmpcache[id][p_idx].next = idx;
158            else
159                    g_bmpcache_lru[id] = idx;
160    
161            if (n_idx >= 0)
162                    g_bmpcache[id][n_idx].previous = idx;
163            else
164                    g_bmpcache_mru[id] = idx;
165    }
166    
167    /* Evict the least-recently used bitmap from the cache */
168    void
169    cache_evict_bitmap(uint8 id)
170    {
171            uint16 idx;
172            int n_idx;
173    
174          pbce = &g_bmpcache[cache_id][cache_idx];          if (!IS_PERSISTENT(id))
175          ui_destroy_bitmap(pbce->bitmap);                  return;
176          --g_num_bitmaps_in_memory[cache_id];  
177          pbce->bitmap = 0;          idx = g_bmpcache_lru[id];
178          pbce->usage = 0;          n_idx = g_bmpcache[id][idx].next;
179            DEBUG_RDP5(("evict bitmap: id=%d idx=%d n_idx=%d bmp=0x%x\n", id, idx, n_idx,
180                        g_bmpcache[id][idx].bitmap));
181    
182            ui_destroy_bitmap(g_bmpcache[id][idx].bitmap);
183            --g_bmpcache_count[id];
184            g_bmpcache[id][idx].bitmap = 0;
185    
186            g_bmpcache_lru[id] = n_idx;
187            g_bmpcache[id][n_idx].previous = NOT_SET;
188    
189            pstcache_touch_bitmap(id, idx, 0);
190  }  }
191    
192  /* Retrieve a bitmap from the cache */  /* Retrieve a bitmap from the cache */
193  HBITMAP  HBITMAP
194  cache_get_bitmap(uint8 cache_id, uint16 cache_idx)  cache_get_bitmap(uint8 id, uint16 idx)
195  {  {
196          HBITMAP *pbitmap;          if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0])))
   
         if ((cache_id < NUM_ELEMENTS(g_bmpcache)) && (cache_idx < NUM_ELEMENTS(g_bmpcache[0])))  
197          {          {
198                  pbitmap = &g_bmpcache[cache_id][cache_idx].bitmap;                  if (g_bmpcache[id][idx].bitmap || pstcache_load_bitmap(id, idx))
                 if ((*pbitmap != 0) || pstcache_load_bitmap(cache_id, cache_idx))  
199                  {                  {
200                          if (IS_PERSISTENT(cache_id))                          if (IS_PERSISTENT(id))
201                                  TOUCH(cache_id, cache_idx);                                  cache_bump_bitmap(id, idx, BUMP_COUNT);
202    
203                          return *pbitmap;                          return g_bmpcache[id][idx].bitmap;
204                  }                  }
205          }          }
206            else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff))
207            {
208                    return g_volatile_bc[id];
209            }
210    
211          error("get bitmap %d:%d\n", cache_id, cache_idx);          error("get bitmap %d:%d\n", id, idx);
212          return NULL;          return NULL;
213  }  }
214    
215  /* Store a bitmap in the cache */  /* Store a bitmap in the cache */
216  void  void
217  cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap, uint32 stamp)  cache_put_bitmap(uint8 id, uint16 idx, HBITMAP bitmap)
218  {  {
219          HBITMAP old;          HBITMAP old;
220    
221          if ((cache_id < NUM_ELEMENTS(g_bmpcache)) && (cache_idx < NUM_ELEMENTS(g_bmpcache[0])))          if ((id < NUM_ELEMENTS(g_bmpcache)) && (idx < NUM_ELEMENTS(g_bmpcache[0])))
222          {          {
223                  old = g_bmpcache[cache_id][cache_idx].bitmap;                  old = g_bmpcache[id][idx].bitmap;
224                  if (old != NULL)                  if (old != NULL)
                 {  
225                          ui_destroy_bitmap(old);                          ui_destroy_bitmap(old);
226                  }                  g_bmpcache[id][idx].bitmap = bitmap;
227                  else  
228                    if (IS_PERSISTENT(id))
229                  {                  {
230                          if (++g_num_bitmaps_in_memory[cache_id] > BMPCACHE2_C2_CELLS)                          if (old == NULL)
231                                  cache_remove_lru_bitmap(cache_id);                                  g_bmpcache[id][idx].previous = g_bmpcache[id][idx].next = NOT_SET;
                 }  
232    
233                  g_bmpcache[cache_id][cache_idx].bitmap = bitmap;                          cache_bump_bitmap(id, idx, TO_TOP);
234                  g_bmpcache[cache_id][cache_idx].usage = stamp;                          if (g_bmpcache_count[id] > BMPCACHE2_C2_CELLS)
235                                    cache_evict_bitmap(id);
236                    }
237            }
238            else if ((id < NUM_ELEMENTS(g_volatile_bc)) && (idx == 0x7fff))
239            {
240                    old = g_volatile_bc[id];
241                    if (old != NULL)
242                            ui_destroy_bitmap(old);
243                    g_volatile_bc[id] = bitmap;
244          }          }
245          else          else
246          {          {
247                  error("put bitmap %d:%d\n", cache_id, cache_idx);                  error("put bitmap %d:%d\n", id, idx);
248          }          }
249  }  }
250    
# Line 112  cache_put_bitmap(uint8 cache_id, uint16 Line 252  cache_put_bitmap(uint8 cache_id, uint16
252  void  void
253  cache_save_state(void)  cache_save_state(void)
254  {  {
255          int id, idx;          uint32 id = 0, t = 0;
256            int idx;
257    
258          for (id = 0; id < NUM_ELEMENTS(g_bmpcache); id++)          for (id = 0; id < NUM_ELEMENTS(g_bmpcache); id++)
259                  if (IS_PERSISTENT(id))                  if (IS_PERSISTENT(id))
260                          for (idx = 0; idx < NUM_ELEMENTS(g_bmpcache[id]); idx++)                  {
261                                  pstcache_touch_bitmap(id, idx, g_bmpcache[id][idx].usage);                          DEBUG_RDP5(("Saving cache state for bitmap cache %d...", id));
262                            idx = g_bmpcache_lru[id];
263                            while (idx >= 0)
264                            {
265                                    pstcache_touch_bitmap(id, idx, ++t);
266                                    idx = g_bmpcache[id][idx].next;
267                            }
268                            DEBUG_RDP5((" %d stamps written.\n", t));
269                    }
270  }  }
271    
272    
# Line 176  cache_get_text(uint8 cache_id) Line 325  cache_get_text(uint8 cache_id)
325  {  {
326          DATABLOB *text;          DATABLOB *text;
327    
328          if (cache_id < NUM_ELEMENTS(g_textcache))          text = &g_textcache[cache_id];
329          {          return text;
                 text = &g_textcache[cache_id];  
                 if (text->data != NULL)  
                         return text;  
         }  
   
         error("get text %d\n", cache_id);  
         return NULL;  
330  }  }
331    
332  /* Store a text item in the cache */  /* Store a text item in the cache */
# Line 193  cache_put_text(uint8 cache_id, void *dat Line 335  cache_put_text(uint8 cache_id, void *dat
335  {  {
336          DATABLOB *text;          DATABLOB *text;
337    
338          if (cache_id < NUM_ELEMENTS(g_textcache))          text = &g_textcache[cache_id];
339          {          if (text->data != NULL)
340                  text = &g_textcache[cache_id];                  xfree(text->data);
341                  if (text->data != NULL)          text->data = xmalloc(length);
342                          xfree(text->data);          text->size = length;
343            memcpy(text->data, data, length);
                 text->data = xmalloc(length);  
                 text->size = length;  
                 memcpy(text->data, data, length);  
         }  
         else  
         {  
                 error("put text %d\n", cache_id);  
         }  
344  }  }
345    
346    

Legend:
Removed from v.726  
changed lines
  Added in v.963

  ViewVC Help
Powered by ViewVC 1.1.26