ソースを参照

Handle the case where pre-allocated LruPages have run out by dynamically allocating new LruPages.
Fix and check for LRU system memory leaks.
Remove unused/bad code (old partial update).
Add unit test #ifdef

aignacio_sf 20 年 前
コミット
cd0b12a41b
2 ファイル変更81 行追加129 行削除
  1. 78 128
      panda/src/dxgsg9/lru.cxx
  2. 3 1
      panda/src/dxgsg9/lru.h

+ 78 - 128
panda/src/dxgsg9/lru.cxx

@@ -1,5 +1,10 @@
 
-//#include "stdafx.h"
+
+#define LRU_UNIT_TEST 0
+
+#if LRU_UNIT_TEST
+#include "stdafx.h"
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -11,7 +16,6 @@
 #define HIGH_PRIORITY_SCALE 4
 #define LOW_PRIORITY_RANGE 25
 
-
 float calculate_exponential_moving_average (float value, float weight, float average)
 {
     return ((value - average) * weight) + average;
@@ -65,7 +69,18 @@ Lru::Lru (int maximum_memory, int maximum_pages)
       this -> _m.lru_page_free_pool = new LruPage * [maximum_pages];
       for (index = 0; index < maximum_pages; index++)
       {
-        this -> _m.lru_page_pool [index] = new LruPage ( );
+        LruPage *lru_page;
+
+        lru_page = new LruPage ( );
+        if (lru_page)
+        {
+          lru_page -> _m.pre_allocated = true;
+          this -> _m.lru_page_pool [index] = lru_page;
+        }
+        else
+        {
+// ERROR
+        }
       }
     }
   }
@@ -74,39 +89,45 @@ Lru::Lru (int maximum_memory, int maximum_pages)
 Lru::~Lru ( )
 {
   int index;
+  LruPage *lru_page;
 
-  for (index = 0; index < LPP_TotalPriorities; index++)
+  // free pre-allocated LruPages
+  if (this -> _m.maximum_pages > 0)
   {
-    LruPage *lru_page;
-    LruPage *next_lru_page;
-
-    if (this -> _m.maximum_pages > 0)
+    if (this -> _m.lru_page_free_pool)
     {
-      if (this -> _m.lru_page_free_pool)
+      for (index = 0; index < this -> _m.maximum_pages; index++)
       {
-        for (index = 0; index < this -> _m.maximum_pages; index++)
+        lru_page = this -> _m.lru_page_pool [index];
+        if (lru_page -> _m.in_lru)
         {
-          delete this -> _m.lru_page_pool [index];
+          this -> remove_page (lru_page);
         }
 
-        delete this -> _m.lru_page_free_pool;
-      }
-      if (this -> _m.lru_page_pool)
-      {
-        delete this -> _m.lru_page_pool;
+        delete lru_page;
       }
+
+      delete this -> _m.lru_page_free_pool;
     }
-    else
+    if (this -> _m.lru_page_pool)
     {
-      lru_page = this -> _m.lru_page_array [index];
-      while (lru_page)
-      {
-        next_lru_page = lru_page -> _m.next;
+      delete this -> _m.lru_page_pool;
+    }
+  }
 
-        delete lru_page;
+  // free dynamically allocated LruPages
+  for (index = 0; index < LPP_TotalPriorities; index++)
+  {
+    LruPage *next_lru_page;
 
-        lru_page = next_lru_page;
-      }
+    lru_page = this -> _m.lru_page_array [index];
+    while (lru_page)
+    {
+      next_lru_page = lru_page -> _m.next;
+
+      delete lru_page;
+
+      lru_page = next_lru_page;
     }
   }
 }
@@ -157,6 +178,8 @@ LruPage * Lru::allocate_page (int size)
       {
         lru_page = this -> _m.lru_page_free_pool [this -> _m.total_lru_pages_in_free_pool - 1];
         this -> _m.total_lru_pages_in_free_pool--;
+
+        memset (&lru_page -> _m, 0, sizeof (LruPage::LruPageVariables));
       }
       else
       {
@@ -167,9 +190,8 @@ LruPage * Lru::allocate_page (int size)
         }
         else
         {
-
-// ERROR: could not allocate LruPage, maximum pages exceeded
-
+          // out of pre-allocated LruPages so dynamically allocate a page
+          lru_page = new LruPage ( );
         }
       }
     }
@@ -184,6 +206,7 @@ LruPage * Lru::allocate_page (int size)
       lru_page -> _m.first_frame_identifier = this -> _m.current_frame_identifier;
       lru_page -> _m.last_frame_identifier = this -> _m.current_frame_identifier;
 
+      lru_page -> _m.allocated = true;
       lru_page -> _m.identifier = this -> _m.identifier;
 
       lru_page -> _m.average_frame_utilization = 1.0f;
@@ -237,12 +260,23 @@ void Lru::free_page (LruPage *lru_page)
     {
       this -> update_start_update_lru_page (lru_page);
 
-      this -> _m.available_memory += lru_page -> _m.size;
+      if (lru_page -> _m.in_cache)
+      {
+        this -> _m.available_memory += lru_page -> _m.size;
+      }
 
-      if (this -> _m.maximum_pages)
+      if (lru_page -> _m.pre_allocated)
       {
-        this -> _m.lru_page_free_pool [this -> _m.total_lru_pages_in_free_pool] = lru_page;
-        this -> _m.total_lru_pages_in_free_pool++;
+        if (this -> _m.maximum_pages)
+        {
+          lru_page -> _m.allocated = false;
+          this -> _m.lru_page_free_pool [this -> _m.total_lru_pages_in_free_pool] = lru_page;
+          this -> _m.total_lru_pages_in_free_pool++;
+        }
+        else
+        {
+// ERROR: this case should not happen
+        }
       }
       else
       {
@@ -276,6 +310,8 @@ void Lru::add_page (LruPagePriority priority, LruPage *lru_page)
     }
 
     this -> _m.lru_page_array [lru_page -> _m.priority] = lru_page;
+
+    lru_page -> _m.in_lru = true;
   }
 }
 
@@ -330,6 +366,8 @@ void Lru::remove_page (LruPage *lru_page)
 
         lru_page -> _m.next = 0;
         lru_page -> _m.previous = 0;
+
+        lru_page -> _m.in_lru = false;
       }
     }
     else
@@ -695,96 +733,6 @@ void Lru::update_entire_lru ( )
   }
 }
 
-void Lru::partial_lru_update_old (int approximate_maximum_updates)
-{
-  int total_page_updates;
-
-  total_page_updates = this -> _m.update_overflow;
-  if (total_page_updates > 0)
-  {
-    this -> _m.update_overflow -= approximate_maximum_updates;
-    if (this -> _m.update_overflow < 0)
-    {
-      this -> _m.update_overflow = 0;
-    }
-  }
-
-  if (this -> _m.total_pages > 0 && total_page_updates < approximate_maximum_updates)
-  {
-    int index;
-    int start_priority;
-    LruPage *lru_page;
-
-    start_priority = this -> _m.start_priority_index;
-
-    {
-      for (index = start_priority; index < LPP_TotalPriorities; index++)
-      {
-        LruPage *next_lru_page;
-
-        lru_page = this -> _m.lru_page_array [index];
-        while (lru_page)
-        {
-          next_lru_page = lru_page -> _m.next;
-
-          this -> update_lru_page (lru_page);
-
-          total_page_updates++;
-
-          lru_page = next_lru_page;
-        }
-
-        if (total_page_updates >= approximate_maximum_updates)
-        {
-          this -> _m.update_overflow = total_page_updates - approximate_maximum_updates;
-          if ((index + 1) < LPP_TotalPriorities)
-          {
-            this -> _m.start_priority_index = index + 1;
-          }
-          break;
-        }
-      }
-    }
-
-    if (total_page_updates < approximate_maximum_updates)
-    {
-      for (index = 0; index < start_priority; index++)
-      {
-        LruPage *next_lru_page;
-
-        lru_page = this -> _m.lru_page_array [index];
-        while (lru_page)
-        {
-          next_lru_page = lru_page -> _m.next;
-
-          this -> update_lru_page (lru_page);
-
-          total_page_updates++;
-
-          lru_page = next_lru_page;
-        }
-
-        if (total_page_updates >= approximate_maximum_updates)
-        {
-          this -> _m.update_overflow = total_page_updates - approximate_maximum_updates;
-          if ((index + 1) < LPP_TotalPriorities)
-          {
-            this -> _m.start_priority_index = index + 1;
-          }
-          break;
-        }
-      }
-    }
-
-    if (index >= LPP_TotalPriorities)
-    {
-      this -> _m.start_priority_index = 0;
-    }
-
-    this -> update_page_priorities ( );
-  }
-}
-
 void Lru::partial_lru_update (int maximum_updates)
 {
   int total_page_updates;
@@ -972,11 +920,8 @@ bool Lru::page_out_lru (int memory_required)
             lru_page -> _m.in_cache = false;
 
             // PAGE OUT CALLBACK
-            {
-              this -> _m.page_out_function_array [lru_page -> _m.type] (lru_page);
-
-              this -> _m.total_lifetime_page_outs++;
-            }
+            this -> _m.page_out_function_array [lru_page -> _m.type] (lru_page);
+            this -> _m.total_lifetime_page_outs++;
 
             // MOVE THE PAGE TO THE LPP_PageOut PRIORITY
             this -> remove_page (lru_page);
@@ -1000,6 +945,7 @@ bool Lru::page_out_lru (int memory_required)
       if (memory_required > 0)
       {
         // WARNING: pages could not be freed, all pages unlocked
+
         this -> unlock_all_pages ( );
         state = false;
       }
@@ -1041,6 +987,8 @@ void Lru::count_priority_level_pages (void)
   }
 }
 
+#if LRU_UNIT_TEST
+
 void test_ema (void)
 {
   int index;
@@ -1077,7 +1025,7 @@ void test_lru (void)
   test_ema ( );
 
   maximum_memory = 3000000;
-  maximum_pages = 1000;
+  maximum_pages = 3;
   lru = new Lru (maximum_memory, maximum_pages);
   if (lru)
   {
@@ -1180,7 +1128,7 @@ void test_lru (void)
       }
     }
 
-    if (true)
+    if (!true)
     {
       lru -> remove_page (lru_page_2);
       lru -> free_page (lru_page_2);
@@ -1195,3 +1143,5 @@ void test_lru (void)
     delete lru;
   }
 }
+
+#endif

+ 3 - 1
panda/src/dxgsg9/lru.h

@@ -58,6 +58,9 @@ public:
       unsigned int in_cache : 1;
       unsigned int in_memory : 1;
       unsigned int on_disk : 1;
+      unsigned int pre_allocated : 1;
+      unsigned int allocated : 1;
+      unsigned int in_lru : 1;
     };
 
     int first_frame_identifier;   // creation time
@@ -119,7 +122,6 @@ public:
 
   void update_entire_lru ( );
   void partial_lru_update (int maximum_updates);
-  void partial_lru_update_old (int approximate_maximum_updates);
 
   // set maximum number of page updates per frame
   // pause/resume updates/current_frame_identifier