~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to app/base/tile-cache.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
18
18
 
19
19
#include "config.h"
20
20
 
21
 
#ifdef USE_PTHREADS
22
 
#include <pthread.h>
23
 
#endif
24
 
 
25
21
#include <glib-object.h>
26
22
 
27
23
#include "base-types.h"
32
28
#include "tile-private.h"
33
29
 
34
30
 
35
 
/*  This is the percentage of the maximum cache size that should be cleared
36
 
 *   from the cache when an eviction is necessary
37
 
 */
38
 
#define FREE_QUANTUM          0.1
39
 
 
40
31
#define IDLE_SWAPPER_TIMEOUT  250
41
32
 
42
33
 
43
34
static gboolean  tile_cache_zorch_next     (void);
44
35
static void      tile_cache_flush_internal (Tile     *tile);
45
36
 
46
 
#ifdef USE_PTHREADS
47
 
static gpointer  tile_idle_thread          (gpointer  data);
48
 
#else
49
37
static gboolean  tile_idle_preswap         (gpointer  data);
50
 
#endif
51
38
 
52
39
 
53
40
static gboolean initialize = TRUE;
64
51
static gulong   cur_cache_dirty = 0;
65
52
static TileList clean_list      = { NULL, NULL };
66
53
static TileList dirty_list      = { NULL, NULL };
67
 
 
68
 
#ifdef USE_PTHREADS
69
 
static pthread_t       preswap_thread;
70
 
static pthread_mutex_t dirty_mutex  = PTHREAD_MUTEX_INITIALIZER;
71
 
static pthread_cond_t  dirty_signal = PTHREAD_COND_INITIALIZER;
72
 
static pthread_mutex_t tile_mutex   = PTHREAD_MUTEX_INITIALIZER;
73
 
#define CACHE_LOCK   pthread_mutex_lock (&tile_mutex)
74
 
#define CACHE_UNLOCK pthread_mutex_unlock (&tile_mutex)
 
54
static guint    idle_swapper    = 0;
 
55
 
 
56
 
 
57
#ifdef ENABLE_MP
 
58
 
 
59
static GStaticMutex   tile_cache_mutex = G_STATIC_MUTEX_INIT;
 
60
 
 
61
#define CACHE_LOCK    g_static_mutex_lock (&tile_cache_mutex)
 
62
#define CACHE_UNLOCK  g_static_mutex_unlock (&tile_cache_mutex)
 
63
 
75
64
#else
76
 
static guint           idle_swapper = 0;
 
65
 
77
66
#define CACHE_LOCK   /* nothing */
78
67
#define CACHE_UNLOCK /* nothing */
 
68
 
79
69
#endif
80
70
 
81
71
 
90
80
      dirty_list.first = dirty_list.last = NULL;
91
81
 
92
82
      max_cache_size = tile_cache_size;
93
 
 
94
 
#ifdef USE_PTHREADS
95
 
      pthread_create (&preswap_thread, NULL, &tile_idle_thread, NULL);
96
 
#else
97
 
      idle_swapper = g_timeout_add (IDLE_SWAPPER_TIMEOUT,
98
 
                                    tile_idle_preswap,
99
 
                                    NULL);
100
 
#endif
101
83
    }
102
84
}
103
85
 
104
86
void
105
87
tile_cache_exit (void)
106
88
{
 
89
  if (idle_swapper)
 
90
    {
 
91
      g_source_remove (idle_swapper);
 
92
      idle_swapper = 0;
 
93
    }
 
94
 
107
95
  tile_cache_set_size (0);
108
96
}
109
97
 
134
122
  if (list)
135
123
    {
136
124
      /* Tile is in the cache.  Remove it from its current list and
137
 
         put it at the tail of the proper list (clean or dirty) */
 
125
         put it at the tail of the proper list (clean or dirty) */
138
126
 
139
127
      if (tile->next)
140
 
        tile->next->prev = tile->prev;
 
128
        tile->next->prev = tile->prev;
141
129
      else
142
 
        list->last = tile->prev;
 
130
        list->last = tile->prev;
143
131
 
144
132
      if (tile->prev)
145
 
        tile->prev->next = tile->next;
 
133
        tile->prev->next = tile->next;
146
134
      else
147
 
        list->first = tile->next;
 
135
        list->first = tile->next;
148
136
 
149
137
      tile->listhead = NULL;
150
138
 
151
139
      if (list == &dirty_list)
152
 
        cur_cache_dirty -= tile_size_inline (tile);
 
140
        cur_cache_dirty -= tile->size;
153
141
    }
154
142
  else
155
143
    {
160
148
       *  it won't be possible to put it in the cache.
161
149
       */
162
150
      while ((cur_cache_size + max_tile_size) > max_cache_size)
163
 
        {
164
 
          if (! tile_cache_zorch_next ())
165
 
            {
166
 
              g_warning ("cache: unable to find room for a tile");
167
 
              goto out;
168
 
            }
169
 
        }
 
151
        {
 
152
          if (! tile_cache_zorch_next ())
 
153
            {
 
154
              g_warning ("cache: unable to find room for a tile");
 
155
              goto out;
 
156
            }
 
157
        }
170
158
 
171
 
      cur_cache_size += tile_size_inline (tile);
 
159
      cur_cache_size += tile->size;
172
160
    }
173
161
 
174
162
  /* Put the tile at the end of the proper list */
191
179
 
192
180
  if (tile->dirty || (tile->swap_offset == -1))
193
181
    {
194
 
      cur_cache_dirty += tile_size_inline (tile);
 
182
      cur_cache_dirty += tile->size;
195
183
 
196
 
#ifdef USE_PTHREADS
197
 
      pthread_mutex_lock (&dirty_mutex);
198
 
      pthread_cond_signal (&dirty_signal);
199
 
      pthread_mutex_unlock (&dirty_mutex);
200
 
#endif
 
184
      if (! idle_swapper &&
 
185
          cur_cache_dirty * 2 > max_cache_size)
 
186
        {
 
187
          idle_swapper = g_timeout_add_full (G_PRIORITY_LOW,
 
188
                                             IDLE_SWAPPER_TIMEOUT,
 
189
                                             tile_idle_preswap,
 
190
                                             NULL, NULL);
 
191
        }
201
192
    }
202
193
 
203
194
out:
226
217
 
227
218
  if (list)
228
219
    {
229
 
      cur_cache_size -= tile_size_inline (tile);
 
220
      cur_cache_size -= tile->size;
230
221
 
231
222
      if (list == &dirty_list)
232
 
        cur_cache_dirty -= tile_size_inline (tile);
 
223
        cur_cache_dirty -= tile->size;
233
224
 
234
225
      if (tile->next)
235
 
        tile->next->prev = tile->prev;
 
226
        tile->next->prev = tile->prev;
236
227
      else
237
 
        list->last = tile->prev;
 
228
        list->last = tile->prev;
238
229
 
239
230
      if (tile->prev)
240
 
        tile->prev->next = tile->next;
 
231
        tile->prev->next = tile->next;
241
232
      else
242
 
        list->first = tile->next;
 
233
        list->first = tile->next;
243
234
 
244
235
      tile->listhead = NULL;
245
236
    }
255
246
 
256
247
  while (cur_cache_size > max_cache_size)
257
248
    {
258
 
      if (!tile_cache_zorch_next ())
259
 
        break;
 
249
      if (! tile_cache_zorch_next ())
 
250
        break;
260
251
    }
261
252
 
262
253
  CACHE_UNLOCK;
275
266
  else
276
267
    return FALSE;
277
268
 
278
 
  CACHE_UNLOCK;
279
 
  TILE_MUTEX_LOCK (tile);
280
 
  CACHE_LOCK;
281
 
 
282
269
  tile_cache_flush_internal (tile);
283
270
 
284
271
  if (tile->dirty || tile->swap_offset == -1)
290
277
    {
291
278
      g_free (tile->data);
292
279
      tile->data = NULL;
293
 
      TILE_MUTEX_UNLOCK (tile);
294
280
 
295
281
      return TRUE;
296
282
    }
297
283
 
298
284
  /* unable to swap out tile for some reason */
299
 
  TILE_MUTEX_UNLOCK (tile);
300
 
 
301
285
  return FALSE;
302
286
}
303
287
 
304
 
 
305
 
#if USE_PTHREADS
306
 
 
307
 
static gpointer
308
 
tile_idle_thread (gpointer data)
309
 
{
310
 
  Tile     *tile;
311
 
  TileList *list;
312
 
  gint      count;
313
 
 
314
 
  g_printerr ("starting tile preswapper thread\n");
315
 
 
316
 
  count = 0;
317
 
  while (TRUE)
318
 
    {
319
 
      CACHE_LOCK;
320
 
 
321
 
      if (count > 5 || dirty_list.first == NULL)
322
 
        {
323
 
          CACHE_UNLOCK;
324
 
 
325
 
          count = 0;
326
 
 
327
 
          pthread_mutex_lock (&dirty_mutex);
328
 
          pthread_cond_wait (&dirty_signal, &dirty_mutex);
329
 
          pthread_mutex_unlock (&dirty_mutex);
330
 
 
331
 
          CACHE_LOCK;
332
 
        }
333
 
 
334
 
      if ((tile = dirty_list.first))
335
 
        {
336
 
          CACHE_UNLOCK;
337
 
          TILE_MUTEX_LOCK (tile);
338
 
          CACHE_LOCK;
339
 
 
340
 
          if (tile->dirty || tile->swap_offset == -1)
341
 
            {
342
 
              list = tile->listhead;
343
 
 
344
 
              if (list == &dirty_list)
345
 
                cur_cache_dirty -= tile_size_inline (tile);
346
 
 
347
 
              if (tile->next)
348
 
                tile->next->prev = tile->prev;
349
 
              else
350
 
                list->last = tile->prev;
351
 
 
352
 
              if (tile->prev)
353
 
                tile->prev->next = tile->next;
354
 
              else
355
 
                list->first = tile->next;
356
 
 
357
 
              tile->next = NULL;
358
 
              tile->prev = clean_list.last;
359
 
              tile->listhead = &clean_list;
360
 
 
361
 
              if (clean_list.last)
362
 
                clean_list.last->next = tile;
363
 
              else
364
 
                clean_list.first = tile;
365
 
 
366
 
              clean_list.last = tile;
367
 
 
368
 
              CACHE_UNLOCK;
369
 
 
370
 
              tile_swap_out (tile);
371
 
            }
372
 
          else
373
 
            {
374
 
              CACHE_UNLOCK;
375
 
            }
376
 
 
377
 
          TILE_MUTEX_UNLOCK (tile);
378
 
        }
379
 
      else
380
 
        {
381
 
          CACHE_UNLOCK;
382
 
        }
383
 
 
384
 
      count++;
385
 
    }
386
 
}
387
 
 
388
 
#else  /* !USE_PTHREADS */
389
 
 
390
288
static gboolean
391
289
tile_idle_preswap (gpointer data)
392
290
{
393
291
  Tile *tile;
394
292
 
395
293
  if (cur_cache_dirty * 2 < max_cache_size)
396
 
    return TRUE;
 
294
    {
 
295
      idle_swapper = 0;
 
296
      return FALSE;
 
297
    }
 
298
 
 
299
  CACHE_LOCK;
397
300
 
398
301
  if ((tile = dirty_list.first))
399
302
    {
402
305
      dirty_list.first = tile->next;
403
306
 
404
307
      if (tile->next)
405
 
        tile->next->prev = NULL;
 
308
        tile->next->prev = NULL;
406
309
      else
407
 
        dirty_list.last = NULL;
 
310
        dirty_list.last = NULL;
408
311
 
409
312
      tile->next = NULL;
410
313
      tile->prev = clean_list.last;
416
319
        clean_list.first = tile;
417
320
 
418
321
      clean_list.last = tile;
419
 
      cur_cache_dirty -= tile_size_inline (tile);
 
322
      cur_cache_dirty -= tile->size;
420
323
    }
421
324
 
 
325
  CACHE_UNLOCK;
 
326
 
422
327
  return TRUE;
423
328
}
424
 
 
425
 
#endif  /* !USE_PTHREADS */