[maemo-commits] [maemo-commits] r18670 - in projects/haf/trunk/libosso: debian src

From: subversion at stage.maemo.org subversion at stage.maemo.org
Date: Tue Jun 9 09:52:04 EEST 2009
Author: kihamala
Date: 2009-06-09 09:51:57 +0300 (Tue, 09 Jun 2009)
New Revision: 18670

Modified:
   projects/haf/trunk/libosso/debian/changelog
   projects/haf/trunk/libosso/src/osso-mem.c
   projects/haf/trunk/libosso/src/osso-mem.h
Log:
applied Leonid's patch for fast memory functions


Modified: projects/haf/trunk/libosso/debian/changelog
===================================================================
--- projects/haf/trunk/libosso/debian/changelog	2009-06-09 06:05:27 UTC (rev 18669)
+++ projects/haf/trunk/libosso/debian/changelog	2009-06-09 06:51:57 UTC (rev 18670)
@@ -1,6 +1,7 @@
 libosso (2.21-1~unreleased) unstable; urgency=low
 
   * Fixes: NB#121151 - libosso coverity findings
+  * Fixes: NB#120686 - fast functions to get amount of memory required
 
  -- Kimmo Hämäläinen <kimmo.hamalainen at nokia.com>  Tue,  9 Jun 2009 08:48:36 +0300
 

Modified: projects/haf/trunk/libosso/src/osso-mem.c
===================================================================
--- projects/haf/trunk/libosso/src/osso-mem.c	2009-06-09 06:05:27 UTC (rev 18669)
+++ projects/haf/trunk/libosso/src/osso-mem.c	2009-06-09 06:51:57 UTC (rev 18670)
@@ -3,7 +3,7 @@
  *
  * This file is part of libosso
  *
- * Copyright (C) 2005-2006 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2005-2009 Nokia Corporation. All rights reserved.
  *
  * Contact: Leonid Moiseichuk <leonid.moiseichuk at nokia.com>
  *
@@ -27,6 +27,7 @@
  * ========================================================================= */
 
 #include <osso-log.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -35,6 +36,7 @@
 #include <pthread.h>
 #include <string.h>
 #include <inttypes.h>
+#include <time.h>
 
 #include "osso-mem.h"
 
@@ -114,8 +116,8 @@
  * ========================================================================= */
 
 /* For lowmem_ functions system limits */
+static size_t sys_avail_ram    = NSIZE;
 static size_t sys_avail_memory = NSIZE;
-static size_t sys_avail_ram    = NSIZE;
 static size_t sys_deny_limit   = NSIZE;
 static size_t sys_lowmem_limit = NSIZE;
 
@@ -148,7 +150,7 @@
 
 static size_t get_file_value(const char* filename)
 {
-   FILE* fp = fopen(filename, "rt");
+   FILE* fp = fopen(filename, "r");
 
    if (fp)
    {
@@ -183,7 +185,7 @@
  * ------------------------------------------------------------------------- */
 static unsigned load_meminfo(size_t *vals, unsigned size)
 {
-   FILE* meminfo = fopen("/proc/meminfo", "rt");
+   FILE* meminfo = fopen("/proc/meminfo", "r");
 
    if ( meminfo )
    {
@@ -222,6 +224,15 @@
 } /* load_meminfo */
 
 /* ------------------------------------------------------------------------- *
+ * get_free_pages - gets the free pages from /proc.
+ * Returns NSIZE if file is not available or value is invalid.
+ * ------------------------------------------------------------------------- */
+static size_t get_free_pages(void)
+{
+   return get_file_value("/proc/sys/vm/lowmem_free_pages");
+} /* get_free_pages */
+
+/* ------------------------------------------------------------------------- *
  * setup_sys_values - loads the values from /proc files or obtain its from
  * system andand setup sys_XXX variables.
  * WARNING: we expect than sys_XXX variables are not changed during runtime.
@@ -232,16 +243,18 @@
    const size_t pagesize = sysconf(_SC_PAGESIZE);
    /* Load amount of allowed pages */
    const size_t allowed_pages = get_file_value("/proc/sys/vm/lowmem_allowed_pages");
+   /* One field Total should be loaded from meminfo */
+   size_t    total   = 0;    /* ID_MEMTOTAL goes first */
+   const int counter = load_meminfo(&total, 1);
 
+   /* Setup available amount of RAM, if no meminfo available set 64MB */
+   sys_avail_ram = (counter && total ? total : (64 << 10));
+
    /* Check the availability of values */
    if (NSIZE == allowed_pages)
    {
-      /* Unfortunately, lowmem_ is not available yet (scratchbox?) */
-      size_t    total   = 0;    /* ID_MEMTOTAL goes first */
-      const int counter = load_meminfo(&total, 1);
-
-      /* Setup available amount of RAM, if no meminfo available set 64MB */
-      sys_avail_memory = (counter && total ? total : (64 << 10));
+      /* Setup available amount of memory */
+      sys_avail_memory = sys_avail_ram;
    }
    else
    {
@@ -257,11 +270,19 @@
       sys_deny_limit = DIVIDE(sys_avail_memory * sys_deny_limit, 100);
 
    if (NSIZE == sys_lowmem_limit)
+   {
+      sys_avail_ram = sys_deny_limit;
       sys_lowmem_limit = sys_deny_limit;
+   }
    else
+   {
+      /* Calibrate amount avaliable RAM and memory using sys_lowmem_limit percentage */
+      sys_avail_ram    = DIVIDE(sys_avail_ram    * sys_lowmem_limit, 100);
       sys_lowmem_limit = DIVIDE(sys_avail_memory * sys_lowmem_limit, 100);
+   }
 
    /* Moving from KB to bytes */
+   sys_avail_ram    <<= 10;
    sys_avail_memory <<= 10;
    sys_deny_limit   <<= 10;
    sys_lowmem_limit <<= 10;
@@ -326,7 +347,10 @@
 
 /* ------------------------------------------------------------------------- *
  * osso_mem_get_usage -- returns memory usage for current system in
- * osso_mem_usage_t structure.
+ * osso_mem_usage_t structure. This function uses cached information
+ * internally because every call is expensive for system. Please use
+ * osso_mem_get_usage_now if you ready to pay for performance penalty.
+ *
  * parameters:
  *    usage - parameters to be updated.
  * returns:
@@ -334,6 +358,60 @@
  * ------------------------------------------------------------------------- */
 int osso_mem_get_usage(osso_mem_usage_t* usage)
 {
+   /* Cached values */
+   static time_t           cache_stamp;
+   static size_t           cache_pfree;
+   static osso_mem_usage_t cache_usage;
+   /* Current values */
+   time_t   stamp;
+   size_t   pfree;
+   int      error;
+
+   /* Check parameter */
+   if ( !usage )
+      return -1;
+
+   /* We should use cached information if calls comes in one second */
+   stamp = time(NULL);
+   if (stamp == cache_stamp)
+   {
+      memcpy(usage, &cache_usage, sizeof(*usage));
+      return 0;
+   }
+
+   /* We should use cached information if amount of free pages not changed */
+   pfree = get_free_pages();
+   if (pfree == cache_pfree)
+   {
+      cache_stamp = stamp;
+      memcpy(usage, &cache_usage, sizeof(*usage));
+      return 0;
+   }
+
+   /* Finally we have to load a new value from /proc/meminfo */
+   error = osso_mem_get_usage_now(usage);
+   if ( !error )
+   {
+      cache_stamp = stamp;
+      cache_pfree = pfree;
+      memcpy(&cache_usage, usage, sizeof(cache_usage));
+   }
+
+   return error;
+} /* osso_mem_get_usage */
+
+/* ------------------------------------------------------------------------- *
+ * osso_mem_get_usage_now -- returns memory usage for current system in
+ * osso_mem_usage_t structure.This function is very expensive for system.
+ * Please use osso_mem_get_usage if you can.
+ *
+ * parameters:
+ *    usage - parameters to be updated.
+ * returns:
+ *    0 if values loaded successfuly OR negative error code.
+ * ------------------------------------------------------------------------- */
+int osso_mem_get_usage_now(osso_mem_usage_t* usage)
+{
    /* Local variables */
    size_t vals[MAX_MEMINFO_LABELS];
 
@@ -351,13 +429,8 @@
    if (NSIZE == sys_avail_memory)
       setup_sys_values();
 
-
    /* Discover memory information using loaded numbers */
    usage->total = vals[ID_MEMTOTAL] + vals[ID_SWAPTOTAL];
-
-   if (NSIZE == sys_avail_ram)
-      sys_avail_ram = vals[ID_MEMTOTAL] << 10;
-
    usage->free  = vals[ID_MEMFREE] + vals[ID_BUFFERS] +
                   vals[ID_CACHED] +  vals[ID_SWAPFREE];
 
@@ -381,23 +454,48 @@
 
    /* We have succeed */
    return 0;
-} /* osso_mem_get_usage */
+} /* osso_mem_get_usage_now */
 
+
+
 /* ------------------------------------------------------------------------- *
  * Returns the total allocated RAM in system according to
- * /proc/sys/vm/lowmem_* files.
+ * /proc/sys/vm/lowmem_* files. If system has swap available only RAM
+ * should be counted.
  *
  * WARNING: Assumes 97% of memory can be allocated if no limits set (kernel)
  * hardcoded threshold.
  * ------------------------------------------------------------------------- */
 size_t osso_mem_get_avail_ram(void)
 {
-   if(NSIZE == sys_avail_memory)
+   if(NSIZE == sys_avail_ram)
       setup_sys_values();
-   return sys_avail_memory;
+   return sys_avail_ram;
 } /* osso_mem_get_avail_ram */
 
 /* ------------------------------------------------------------------------- *
+ * Returns amount of currently available memory in system below high memory
+ * usage watermark. If system has swap available it also counted.
+ * ------------------------------------------------------------------------- */
+size_t osso_mem_get_free(void)
+{
+   static size_t pg_high;
+   static size_t pg_size;
+   const  size_t pg_free = get_free_pages();
+
+   if ( !pg_high )
+   {
+      pg_high = get_file_value("/proc/sys/vm/lowmem_notify_high_pages");
+      pg_size = sysconf(_SC_PAGESIZE);
+   }
+
+   if (NSIZE == pg_high || NSIZE == pg_free)
+      return osso_mem_get_avail_ram();
+   else
+      return (pg_free > pg_high ? (pg_free - pg_high) * pg_size: 0);
+} /* osso_mem_get_free */
+
+/* ------------------------------------------------------------------------- *
  * Returns deny limit (in bytes, the total allocated RAM in system)
  * according to /proc/sys/vm/lowmem_* settings.
  *
@@ -534,7 +632,21 @@
 } /* osso_mem_saw_disable */
 
 
+/* ------------------------------------------------------------------------- *
+ * osso_mem_score_adjust - adjust out of memory handling by set
+ * /proc/self/oom_adj to most system-friendly value (15)
+ *
+ * Returns: 0 on success, negative on error
+ * ------------------------------------------------------------------------- */
+int osso_mem_score_adjust(void)
+{
+   int fd = open("/proc/self/oom_adj", O_WRONLY);
+   int rs = (fd >= 0 && 2 == write(fd, "15", 2) ? 0 : -1);
+   close(fd);
+   return rs;
+} /* osso_mem_score_adjust */
 
+
 /* ========================================================================= *
  * main function, just for testing purposes.
  * ========================================================================= */
@@ -552,8 +664,9 @@
    const size_t insane = 60 << 20;
    void* ptr;
 
-   printf("\n1. UNIT_TEST MEMUSAGE \n");
+   printf("\n* osso_mem_score_adjust() called to update oom_adj: %d\n", osso_mem_score_adjust());
 
+   printf("\n* unit testing for osso_mem_get_usage\n");
    /* Load all values from meminfo file */
    if (0 == osso_mem_get_usage(&usage))
    {
@@ -564,15 +677,22 @@
       printf ("unable to load values from /proc/meminfo file\n");
       return -1;
    }
+   /* Make a sleeps and another calls */
+   usleep(1 * 1000 * 1000);
+   osso_mem_get_usage(&usage);
+   usleep(2 * 1000 * 1000);
+   osso_mem_get_usage(&usage);
+   usleep(3 * 1000 * 1000);
+   osso_mem_get_usage(&usage);
 
-   printf("\n2. Testing lowmem\n");
+   printf("\n* Testing lowmem\n");
 
    printf("Lowmem limits: LOW=%u bytes, DENY=%u bytes\n",
             osso_mem_get_lowmem_limit(),
             osso_mem_get_deny_limit()
          );
 
-   printf("\n3. Testing SAW\n");
+   printf("\n* Testing SAW\n");
    ptr = malloc( insane );
    printf("Without SAW, allocating %u bytes: %s\n",insane, ptr ? "Succeeded": "Failed" );
 
@@ -596,10 +716,13 @@
    printf("With SAW, allocating %u bytes: %s\n", insane, ptr ? "Succeeded" : "Failed");
 
    if ( osso_mem_in_lowmem_state() )
-      printf("\n4. Low memory situation is reached\n");
+      printf("\n* Low memory situation is reached\n");
    else
-      printf("\n4. Low memory situation is not reached\n");
+      printf("\n* Low memory situation is not reached\n");
 
+   printf("\n* RAM available %u\n", osso_mem_get_avail_ram());
+   printf("\n* free memory available %u\n", osso_mem_get_free());
+
    if(ptr)
       free(ptr);
 

Modified: projects/haf/trunk/libosso/src/osso-mem.h
===================================================================
--- projects/haf/trunk/libosso/src/osso-mem.h	2009-06-09 06:05:27 UTC (rev 18669)
+++ projects/haf/trunk/libosso/src/osso-mem.h	2009-06-09 06:51:57 UTC (rev 18670)
@@ -3,7 +3,7 @@
  *
  * This file is part of libosso
  *
- * Copyright (C) 2005-2006 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2005-2009 Nokia Corporation. All rights reserved.
  *
  * Contact: Leonid Moiseichuk <leonid.moiseichuk at nokia.com>
  *
@@ -64,39 +64,57 @@
  * ========================================================================= */
 
 /* ------------------------------------------------------------------------- *
- * osso_mem_get_usage -- returns memory usage for current system in
- * osso_mem_usage_t structure.
+ * osso_mem_get_usage -- returns current memory usage in the system in a
+ * osso_mem_usage_t structure. This function uses cached information
+ * internally because every call is expensive for the system. Please use
+ * osso_mem_get_usage_now if you are ready to pay the performance penalty.
+ *
  * parameters:
  *    usage - parameters to be updated.
  * returns:
- *    0 if values loaded successfuly OR negative error code.
+ *    0 if values loaded successfully OR negative error code.
  * ------------------------------------------------------------------------- */
 int osso_mem_get_usage(osso_mem_usage_t* usage);
 
 /* ------------------------------------------------------------------------- *
- * Returns the total allocated RAM in system	according to
- * /proc/sys/vm/lowmem_* files.
+ * osso_mem_get_usage_now -- returns current memory usage in the system in a
+ * osso_mem_usage_t structure. This function is very expensive for the system.
+ * Please use osso_mem_get_usage if you can.
  *
- * WARNING: Assumes 97% of memory can be allocated if no limits set (kernel)
- * hardcoded threshold.
+ * parameters:
+ *    usage - parameters to be updated.
+ * returns:
+ *    0 if values loaded successfuly OR negative error code.
  * ------------------------------------------------------------------------- */
+int osso_mem_get_usage_now(osso_mem_usage_t* usage);
+
+/* ------------------------------------------------------------------------- *
+ * Returns the total allocated RAM in the system according to
+ * /proc/sys/vm/lowmem_* files. The return value concerns only RAM, not swap.
+ *
+ * WARNING: Assumes that 97% of the free RAM can be allocated.
+ * ------------------------------------------------------------------------- */
 size_t osso_mem_get_avail_ram(void);
 
 /* ------------------------------------------------------------------------- *
- * Returns deny limit (in bytes, the total allocated RAM in system)
+ * Returns the amount of currently free memory in the system below the high
+ * memory usage watermark. If the system has swap available, it is also counted.
+ * ------------------------------------------------------------------------- */
+size_t osso_mem_get_free(void);
+
+/* ------------------------------------------------------------------------- *
+ * Returns the deny limit (in bytes, the total allocated RAM in system)
  * according to /proc/sys/vm/lowmem_* settings.
  *
- * WARNING: Assumes 97% of memory can be allocated if no limits set (kernel)
- * hardcoded threshold.
+ * WARNING: Assumes that 97% of the free RAM can be allocated.
  * ------------------------------------------------------------------------- */
 size_t osso_mem_get_deny_limit(void);
 
 /* ------------------------------------------------------------------------- *
- * Returns low memory (lowmem_high_limit, the total allocated RAM in system)
+ * Returns the low memory (lowmem_high_limit, the total allocated RAM in system)
  * according to /proc/sys/vm/lowmem_* settings.
  *
- * WARNING: Assumes 97% of memory can be allocated if no limits set (kernel)
- * hardcoded threshold.
+ * WARNING: Assumes that 97% of the free RAM can be allocated.
  * ------------------------------------------------------------------------- */
 size_t osso_mem_get_lowmem_limit(void);
 
@@ -109,20 +127,20 @@
 
 /* ------------------------------------------------------------------------- *
  * osso_mem_saw_enable - enables Simple Allocation Watchdog.
- * 1. Calculates the possible growth of process' heap based on the
- *    current heap stats, adjusted to the threshold
- * 2. sets up the hook on malloc function; if the particular allocatuion
- *    whose size is bigger than watchblock_sz could violate the limit,
- *    oom_func with user-specified context is called and malloc returns 0
+ * 1. Calculates the possible growth of the process' heap based on the
+ *    current heap stats, adjusted to the threshold.
+ * 2. Sets up the hook on malloc function; if the particular allocation,
+ *    whose size is bigger than watchblock_sz, could violate the limit,
+ *    oom_func with user-specified context is called and malloc returns 0.
  *
  * Parameters:
- * - threshold - amount of memory used in system. If you pass 0 than maximum
+ * - threshold - amount of memory used in system. If you pass 0, then maximum
  *   available should be set (according to lowmem_high_limit)
- * - watchblock - if allocation size more than specified the amount of
- *   available memory must be tested. If 0 passed this parameter should be
- *   set to page size.
- * - oom_func - this function shall be called if we reach high memory
- *   consumption (OOM level), specified by threshold or NULL malloc occurs.
+ * - watchblock - if allocation size is more than this, the amount of
+ *   available memory is (re)checked. If 0 is passed, this parameter will be
+ *   set to the page size.
+ * - oom_func - this function will be called if we reach high memory
+ *   consumption (OOM level), the threshold level, or if malloc returns NULL.
  *   May be NULL.
  * - context - additional parameter that shall be passed into oom_func.
  *
@@ -130,7 +148,7 @@
  *
  * Note: can be safely called several times.
  *
- * WARNING: if SAW can not be installed the old one will be active.
+ * WARNING: if SAW can not be installed, the old one will be active.
  * ------------------------------------------------------------------------- */
 int osso_mem_saw_enable(size_t threshold,
                size_t watchblock,
@@ -140,10 +158,18 @@
 
 /* ------------------------------------------------------------------------- *
  * osso_mem_saw_disable - disables Simple Allocation Watchdog and restore
- * default malloc hook. If no watchdog setup do nothing.
+ * the default malloc hook. If no watchdog was set up, do nothing.
  * ------------------------------------------------------------------------- */
 void osso_mem_saw_disable(void);
 
+/* ------------------------------------------------------------------------- *
+ * osso_mem_out_adjust - adjust out of memory handling by setting
+ * /proc/self/oom_adj to the most system-friendly value (15)
+ *
+ * Returns: 0 on success, negative on error
+ * ------------------------------------------------------------------------- */
+int osso_mem_score_adjust(void);
+
 #ifdef __cplusplus
 }
 #endif


More information about the maemo-commits mailing list