afs: Make afs_osi_Free(NULL) a no-op
[openafs.git] / src / afs / afs_osi_alloc.c
index 9fcc118..4ca4987 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include "afs/param.h"
 
-RCSID("$Header$");
 
 
 
 #include "afs/sysincludes.h"   /* Standard vendor system headers */
 #include "afsincludes.h"       /* Afs-based standard headers */
-#include "afs/afs_stats.h"   /* afs statistics */
+#include "afs/afs_stats.h"     /* afs statistics */
+
+
 
 #ifdef AFS_AIX41_ENV
 #include "sys/lockl.h"
 #include "sys/sleep.h"
 #include "sys/syspest.h"
 #include "sys/lock_def.h"
-/*lock_t osi_fsplock = LOCK_AVAIL;*/
-#else
-afs_lock_t osi_fsplock;
 #endif
 
+#ifndef AFS_PRIVATE_OSI_ALLOCSPACES
 
+afs_lock_t osi_fsplock;
+afs_lock_t osi_flplock;
 
 static struct osi_packet {
     struct osi_packet *next;
-} *freePacketList = 0, *freeSmallList, *freeMediumList;
-afs_lock_t osi_flplock;
+} *freePacketList = NULL, *freeSmallList = NULL;
 
+#endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
 
-afs_int32 afs_preallocs = 512; /* Reserve space for all small allocs! */
-void osi_AllocMoreSSpace(register afs_int32 preallocs)
-{
-    register int i;
-    char *p;
+static char memZero;           /* address of 0 bytes for kmem_alloc */
 
-    p = (char *) afs_osi_Alloc(AFS_SMALLOCSIZ * preallocs);
-#ifdef  KERNEL_HAVE_PIN
-    pin(p, AFS_SMALLOCSIZ * preallocs);        /* XXXX */
+void *
+afs_osi_Alloc(size_t size)
+{
+    AFS_STATCNT(osi_Alloc);
+    /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
+     * things so that NULL returned iff an error occurred */
+    if (size == 0)
+       return &memZero;
+
+    AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
+    AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += size);
+#ifdef AFS_LINUX20_ENV
+    return osi_linux_alloc(size, 1);
+#elif defined(AFS_FBSD_ENV)
+    return osi_fbsd_alloc(size, 1);
+#else
+    return AFS_KALLOC(size);
 #endif
-    for (i=0; i < preallocs; i++, p += AFS_SMALLOCSIZ) {
-#ifdef AFS_AIX32_ENV
-       *p = '\0'; /* page fault it in. */
+}
+
+void
+afs_osi_Free(void *x, size_t asize)
+{
+    AFS_STATCNT(osi_Free);
+    if (x == &memZero || x == NULL)
+       return;                 /* check for putting memZero back */
+
+    AFS_STATS(afs_stats_cmperf.OutStandingAllocs--);
+    AFS_STATS(afs_stats_cmperf.OutStandingMemUsage -= asize);
+#if defined(AFS_LINUX20_ENV)
+    osi_linux_free(x);
+#elif defined(AFS_FBSD_ENV)
+    osi_fbsd_free(x);
+#else
+    AFS_KFREE(x, asize);
 #endif
-       osi_FreeSmallSpace((char *) p);
-    }
-    afs_stats_cmperf.SmallBlocksAlloced += preallocs;
-    afs_stats_cmperf.SmallBlocksActive  += preallocs;
 }
 
+void
+afs_osi_FreeStr(char *x)
+{
+    afs_osi_Free(x, strlen(x) + 1);
+}
 
+#ifndef AFS_PRIVATE_OSI_ALLOCSPACES
 
 /* free space allocated by AllocLargeSpace.  Also called by mclput when freeing
  * a packet allocated by osi_NetReceive. */
 
-void osi_FreeLargeSpace(void *adata)
+void
+osi_FreeLargeSpace(void *adata)
 {
 
     AFS_ASSERT_GLOCK();
 
     AFS_STATCNT(osi_FreeLargeSpace);
     afs_stats_cmperf.LargeBlocksActive--;
-    MObtainWriteLock(&osi_flplock,322);
+    ObtainWriteLock(&osi_flplock, 322);
     ((struct osi_packet *)adata)->next = freePacketList;
     freePacketList = adata;
-    MReleaseWriteLock(&osi_flplock);
+    ReleaseWriteLock(&osi_flplock);
 }
 
-void osi_FreeSmallSpace(void *adata)
+void
+osi_FreeSmallSpace(void *adata)
 {
 
-#if    defined(AFS_AIX32_ENV)
-    int x;
-#endif
-#if    defined(AFS_HPUX_ENV)
-    ulong_t x;
-#endif
-
     AFS_ASSERT_GLOCK();
 
     AFS_STATCNT(osi_FreeSmallSpace);
     afs_stats_cmperf.SmallBlocksActive--;
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    x = splnet();      /*lockl(&osi_fsplock, LOCK_SHORT);*/
-#else
-    MObtainWriteLock(&osi_fsplock,323);
-#endif
+    ObtainWriteLock(&osi_fsplock, 323);
     ((struct osi_packet *)adata)->next = freeSmallList;
     freeSmallList = adata;
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    splx(x);           /*unlockl(&osi_fsplock);*/
-#else
-    MReleaseWriteLock(&osi_fsplock);
-#endif
+    ReleaseWriteLock(&osi_fsplock);
 }
 
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-osi_AllocMoreMSpace(register afs_int32 preallocs)
-{
-    register int i;
-    char *p;
-
-    p = (char *) afs_osi_Alloc(AFS_MDALLOCSIZ * preallocs);
-#ifdef  KERNEL_HAVE_PIN
-    pin(p, AFS_MDALLOCSIZ * preallocs);        /* XXXX */
-#endif
-    for (i=0; i < preallocs; i++, p += AFS_MDALLOCSIZ) {
-#ifdef AFS_AIX32_ENV
-       *p = '\0'; /* page fault it in. */
-#endif
-       osi_FreeMediumSpace((char *) p);
-    }
-    afs_stats_cmperf.MediumBlocksAlloced += preallocs;
-    afs_stats_cmperf.MediumBlocksActive  += preallocs;
-}
-
-
-void *osi_AllocMediumSpace(size_t size) 
-{
-    register struct osi_packet *tp;
-#if    defined(AFS_AIX32_ENV)
-    int x;
-#endif
-#if    defined(AFS_HPUX_ENV)
-    ulong_t x;
-#endif
-
-    afs_stats_cmperf.MediumBlocksActive++;
- retry:
-    x = splnet();
-    tp = freeMediumList;
-    if ( tp ) freeMediumList = tp->next;
-    splx(x);
-    if (!tp) {
-       osi_AllocMoreMSpace(AFS_MALLOC_LOW_WATER); 
-       goto retry;
-    }
-    return tp;
-}
-
-void osi_FreeMediumSpace(void *adata)
-{
-
-#if    defined(AFS_AIX32_ENV)
-    int x;
-#endif
-#if    defined(AFS_HPUX_ENV)
-    ulong_t x;
-#endif
-
-    afs_stats_cmperf.MediumBlocksActive--;
-    x = splnet();
-    ((struct osi_packet *)adata)->next = freeMediumList;
-    freeMediumList = adata;
-    splx(x);
-}
-#endif /* defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV) */
-
 
 /* allocate space for sender */
-void *osi_AllocLargeSpace(size_t size) 
+void *
+osi_AllocLargeSpace(size_t size)
 {
-    register struct osi_packet *tp;
+    struct osi_packet *tp;
 
     AFS_ASSERT_GLOCK();
 
     AFS_STATCNT(osi_AllocLargeSpace);
     if (size > AFS_LRALLOCSIZ)
-       osi_Panic("osi_AllocLargeSpace: size=%d\n", size);
+       osi_Panic("osi_AllocLargeSpace: size=%d\n", (int)size);
     afs_stats_cmperf.LargeBlocksActive++;
     if (!freePacketList) {
        char *p;
 
        afs_stats_cmperf.LargeBlocksAlloced++;
-       p = (char *) afs_osi_Alloc(AFS_LRALLOCSIZ);
+       p = afs_osi_Alloc(AFS_LRALLOCSIZ);
 #ifdef  KERNEL_HAVE_PIN
        /*
         * Need to pin this memory since under heavy conditions this memory
-         * could be swapped out; the problem is that we could inside rx where
-         * interrupts are disabled and thus we would panic if we don't pin it.
-         */
-       pin(p, AFS_LRALLOCSIZ); 
+        * could be swapped out; the problem is that we could inside rx where
+        * interrupts are disabled and thus we would panic if we don't pin it.
+        */
+       pin(p, AFS_LRALLOCSIZ);
 #endif
        return p;
     }
-    MObtainWriteLock(&osi_flplock,324);
+    ObtainWriteLock(&osi_flplock, 324);
     tp = freePacketList;
-    if ( tp ) freePacketList = tp->next;
-    MReleaseWriteLock(&osi_flplock);
-    return (char *) tp;
+    if (tp)
+       freePacketList = tp->next;
+    ReleaseWriteLock(&osi_flplock);
+    return (char *)tp;
 }
 
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-/*
- * XXX We could have used a macro around osi_AllocSmallSpace but it's
- * probably better like this so that we can remove this at some point.
- */
-/* morespace 1 - means we called at splnet level */
-char *osi_AllocSmall(register afs_int32 size, register afs_int32 morespace) 
-{
-    register struct osi_packet *tp;
-#if    defined(AFS_AIX32_ENV)
-    int x;
-#endif
-#if    defined(AFS_HPUX_ENV)
-    ulong_t x;
-#endif
-
-    AFS_ASSERT_GLOCK();
-
-    AFS_STATCNT(osi_AllocSmallSpace);
-    if (size > AFS_SMALLOCSIZ) osi_Panic("osi_AllocSmall, size=%d", size);
-    if ((!morespace && 
-        ((afs_stats_cmperf.SmallBlocksAlloced - afs_stats_cmperf.SmallBlocksActive)
-         <= AFS_SALLOC_LOW_WATER)) 
-       || !freeSmallList) {
-       osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
-    }
-    afs_stats_cmperf.SmallBlocksActive++;
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    x = splnet();      /*lockl(&osi_fsplock, LOCK_SHORT);*/
-#else
-    MObtainWriteLock(&osi_fsplock,325);
-#endif
-    tp = freeSmallList;
-    if ( tp ) freeSmallList = tp->next;
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    splx(x);           /*unlockl(&osi_fsplock);*/
-#else
-    MReleaseWriteLock(&osi_fsplock);
-#endif
-
-    return (char *) tp;
-}
-
-int osi_FreeSmall(register struct osi_packet *adata)
-{
-#if    defined(AFS_AIX32_ENV)
-    int x;
-#endif
-#if    defined(AFS_HPUX_ENV)
-    ulong_t x;
-#endif
-
-    AFS_STATCNT(osi_FreeSmallSpace);
-    afs_stats_cmperf.SmallBlocksActive--;
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    x = splnet();      /*lockl(&osi_fsplock, LOCK_SHORT);*/
-#else
-    MObtainWriteLock(&osi_fsplock,326);
-#endif
-    adata->next = freeSmallList;
-    freeSmallList = adata;
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    splx(x);           /*unlockl(&osi_fsplock);*/
-#else
-    MReleaseWriteLock(&osi_fsplock);
-#endif
-    return 0;
-}
-#endif /* AFS_AIX32_ENV || AFS_HPUX_ENV */
 
 /* allocate space for sender */
-void *osi_AllocSmallSpace(size_t size) 
+void *
+osi_AllocSmallSpace(size_t size)
 {
-    register struct osi_packet *tp;
-#if    defined(AFS_AIX32_ENV)
-    int x;
-#endif
-#if    defined(AFS_HPUX_ENV)
-    ulong_t x;
-#endif
+    struct osi_packet *tp;
 
     AFS_STATCNT(osi_AllocSmallSpace);
-    if (size > AFS_SMALLOCSIZ) osi_Panic("osi_AllocSmallS: size=%d\n", size);
-
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    /* 
-     * We're running out of free blocks (< 50); get some more ourselves so that
-     * when we don't run out of them when called under splnet() (from rx);
-     */
-    if (((afs_stats_cmperf.SmallBlocksAlloced - afs_stats_cmperf.SmallBlocksActive)
-         <= AFS_SALLOC_LOW_WATER) || !freeSmallList) {
-       osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
-    }
-#else
+    if (size > AFS_SMALLOCSIZ)
+       osi_Panic("osi_AllocSmallS: size=%d\n", (int)size);
+
     if (!freeSmallList) {
        afs_stats_cmperf.SmallBlocksAlloced++;
        afs_stats_cmperf.SmallBlocksActive++;
-       return afs_osi_Alloc(AFS_SMALLOCSIZ);
-    }
+       tp = afs_osi_Alloc(AFS_SMALLOCSIZ);
+#ifdef KERNEL_HAVE_PIN
+        pin((char *)tp, AFS_SMALLOCSIZ);
 #endif
+        return (char *)tp;
+    }
     afs_stats_cmperf.SmallBlocksActive++;
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    x = splnet();      /*lockl(&osi_fsplock, LOCK_SHORT);*/
-#else
-    MObtainWriteLock(&osi_fsplock,327);
-#endif
+    ObtainWriteLock(&osi_fsplock, 327);
     tp = freeSmallList;
-    if ( tp ) freeSmallList = tp->next;
-#if    defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
-    splx(x);           /*unlockl(&osi_fsplock);*/
-#else
-    MReleaseWriteLock(&osi_fsplock);
-#endif
-    return (char *) tp;
+    if (tp)
+       freeSmallList = tp->next;
+    ReleaseWriteLock(&osi_fsplock);
+    return (char *)tp;
 }
+#endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
 
-
-
-void shutdown_osinet(void)
-{   
-  extern int afs_cold_shutdown;
-
-  AFS_STATCNT(shutdown_osinet);
-  if (afs_cold_shutdown) {
-    struct osi_packet *tp;
-
-    while ((tp = freePacketList)) {
-      freePacketList = tp->next;
-      afs_osi_Free(tp, AFS_LRALLOCSIZ);
+void
+shutdown_osinet(void)
+{
+    AFS_STATCNT(shutdown_osinet);
+#ifndef AFS_PRIVATE_OSI_ALLOCSPACES
+    if (afs_cold_shutdown) {
+       struct osi_packet *tp;
+
+       while ((tp = freePacketList)) {
+           freePacketList = tp->next;
+           afs_osi_Free(tp, AFS_LRALLOCSIZ);
 #ifdef  KERNEL_HAVE_PIN
-      unpin(tp, AFS_LRALLOCSIZ);       
+           unpin(tp, AFS_LRALLOCSIZ);
 #endif
-    }
+       }
 
-    while ((tp = freeSmallList)) {
-      freeSmallList = tp->next;
-      afs_osi_Free(tp, AFS_SMALLOCSIZ);
+       while ((tp = freeSmallList)) {
+           freeSmallList = tp->next;
+           afs_osi_Free(tp, AFS_SMALLOCSIZ);
 #ifdef  KERNEL_HAVE_PIN
-      unpin(tp, AFS_SMALLOCSIZ);       
+           unpin(tp, AFS_SMALLOCSIZ);
 #endif
+       }
+       LOCK_INIT(&osi_fsplock, "osi_fsplock");
+       LOCK_INIT(&osi_flplock, "osi_flplock");
+    }
+#endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
+    if (afs_stats_cmperf.LargeBlocksActive ||
+       afs_stats_cmperf.SmallBlocksActive)
+    {
+       afs_warn("WARNING: not all blocks freed: large %d small %d\n",
+                afs_stats_cmperf.LargeBlocksActive,
+                afs_stats_cmperf.SmallBlocksActive);
     }
-    afs_preallocs = 512;
-#ifndef        AFS_AIX32_ENV
-    LOCK_INIT(&osi_fsplock, "osi_fsplock");
-#endif
-    LOCK_INIT(&osi_flplock, "osi_flplock");
-  }
 }