LCOV - code coverage report
Current view: top level - src - cq.c (source / functions) Hit Total Coverage
Test: app.info Lines: 0 292 0.0 %
Date: 2010-12-13 Functions: 0 13 0.0 %
Branches: 0 172 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * See the file "COPYING" in the main distribution directory for copyright.
       3                 :            :  */
       4                 :            : 
       5                 :            : #ifndef lint
       6                 :            : static const char rcsid[] =
       7                 :            :     "@(#) $Id: cq.c 6219 2008-10-01 05:39:07Z vern $ (LBL)";
       8                 :            : #endif
       9                 :            : 
      10                 :            : #include <sys/types.h>
      11                 :            : 
      12                 :            : #include <errno.h>
      13                 :            : #include <stdio.h>
      14                 :            : #include <stdlib.h>
      15                 :            : #include <string.h>
      16                 :            : #ifdef HAVE_MEMORY_H
      17                 :            : #include <memory.h>
      18                 :            : #endif
      19                 :            : #include <math.h>
      20                 :            : 
      21                 :            : #ifdef CQ_DEVELOPMENT
      22                 :            : #include <lbl/gnuc.h>
      23                 :            : #include <lbl/os-proto.h>
      24                 :            : #endif
      25                 :            : 
      26                 :            : #include "cq.h"
      27                 :            : 
      28                 :            : /* Priority to virtual bucket (int) */
      29                 :            : #define PRI2VBUCKET(hp, p) ((int)((p) / (hp)->bwidth))
      30                 :            : 
      31                 :            : /* Priority to bucket (int) */
      32                 :            : #define PRI2BUCKET(hp, p) \
      33                 :            :     ((int)fmod((p) / (hp)->bwidth, (double)((hp)->nbuckets)))
      34                 :            : 
      35                 :            : /* Priority to bucket top (double) */
      36                 :            : #define PRI2BUCKETTOP(hp, p) ((hp)->bwidth * (((p) / (hp)->bwidth) + 1.5))
      37                 :            : 
      38                 :            : /* True if bucket is in use */
      39                 :            : #define BUCKETINUSE(bp) ((bp)->cookie != NULL)
      40                 :            : 
      41                 :            : /* Private data */
      42                 :            : struct cq_handle {
      43                 :            :         int nbuckets;                   /* number of buckets */
      44                 :            :         int qlen;                       /* number of queued entries */
      45                 :            :         int max_qlen;                   /* max. number of queued entries */
      46                 :            :         int himark;                     /* high bucket threshold */
      47                 :            :         int lowmark;                    /* low bucket threshold */
      48                 :            :         int nextbucket;                 /* next bucket to check */
      49                 :            :         int noresize;                   /* don't resize while we're resizing */
      50                 :            :         double lastpri;                 /* last priority */
      51                 :            :         double ysize;                   /* length of a year */
      52                 :            :         double bwidth;                  /* width of each bucket */
      53                 :            :         double buckettop;               /* priority of top of current bucket */
      54                 :            :         struct cq_bucket *buckets;      /* array of buckets */
      55                 :            : };
      56                 :            : 
      57                 :            : struct cq_bucket {
      58                 :            :         double pri;
      59                 :            :         void *cookie;
      60                 :            :         struct cq_bucket *next;
      61                 :            : };
      62                 :            : 
      63                 :            : #ifdef DEBUG
      64                 :            : #ifdef CQ_DEVELOPMENT
      65                 :            : extern int debug;
      66                 :            : #else
      67                 :            : int debug = 0;
      68                 :            : #endif
      69                 :            : #endif
      70                 :            : 
      71                 :            : static unsigned int memory_allocation = 0;
      72                 :            : 
      73                 :            : static struct cq_bucket *free_list = 0;
      74                 :            : 
      75                 :            : /* Forwards */
      76                 :            : static int cq_resize(struct cq_handle *, int);
      77                 :            : static void cq_destroybuckets(struct cq_bucket *, int);
      78                 :            : #ifdef DEBUG
      79                 :            : static int cq_debugbucket(struct cq_handle *, struct cq_bucket *);
      80                 :            : void cq_debug(struct cq_handle *, int);
      81                 :            : #endif
      82                 :            : 
      83                 :            : 
      84                 :            : /* Initialize a calendar queue */
      85                 :            : struct cq_handle *
      86                 :            : cq_init(register double ysize, register double placebo)
      87                 :          0 : {
      88                 :            :         register struct cq_handle *hp;
      89                 :            : 
      90                 :            : #ifdef DEBUG
      91         [ #  # ]:          0 :         if (debug > 1)
      92                 :          0 :                 fprintf(stderr, "cq_init(%f)\n", ysize);
      93                 :            : #endif
      94                 :            :         /* The year size be positive */
      95         [ #  # ]:          0 :         if (ysize <= 0.0) {
      96                 :          0 :                 errno = EINVAL;
      97                 :          0 :                 return (NULL);
      98                 :            :         }
      99                 :            : 
     100                 :            :         /* Allocate handle */
     101                 :          0 :         hp = (struct cq_handle *)malloc(sizeof(*hp));
     102                 :          0 :         memory_allocation += sizeof(*hp);
     103         [ #  # ]:          0 :         if (hp == NULL)
     104                 :          0 :                 return (NULL);
     105         [ #  # ]:          0 :         memset(hp, 0, sizeof(*hp));
     106                 :            : 
     107                 :            :         /* Initialize handle */
     108                 :          0 :         hp->ysize = ysize;
     109                 :          0 :         hp->max_qlen = 0;
     110                 :            : 
     111                 :            :         /* Allocate initial buckets and finish handle initialization */
     112         [ #  # ]:          0 :         if (cq_resize(hp, 0) < 0) {
     113                 :          0 :                 free(hp);
     114                 :          0 :                 memory_allocation -= sizeof(*hp);
     115                 :          0 :                 return (NULL);
     116                 :            :         }
     117                 :          0 :         return (hp);
     118                 :            : }
     119                 :            : 
     120                 :            : /* Returns zero on success, -1 on error (with errno set) */
     121                 :            : int
     122                 :            : cq_enqueue(register struct cq_handle *hp, register double pri,
     123                 :            :     register void *cookie)
     124                 :          0 : {
     125                 :            :         register struct cq_bucket *bp, *bp2;
     126                 :            : #ifdef DEBUG
     127                 :            :         register int q1, q2;
     128                 :            :         register struct cq_bucket *buckethead;
     129                 :            : #endif
     130                 :            : 
     131                 :            : #ifdef DEBUG
     132         [ #  # ]:          0 :         if (debug > 1)
     133                 :          0 :                 fprintf(stderr, "cq_enqueue(%f)\n", pri);
     134                 :            : #endif
     135                 :            : 
     136                 :            :         /* The priority must be positive and the cookie non-null */
     137 [ #  # ][ #  # ]:          0 :         if (pri <= 0.0 || cookie == NULL) {
     138                 :          0 :                 errno = EINVAL;
     139                 :          0 :                 return (-1);
     140                 :            :         }
     141                 :            : 
     142                 :            :         /* We might as well resize now if we're going to need to */
     143 [ #  # ][ #  # ]:          0 :         if (hp->qlen + 1 > hp->himark && cq_resize(hp, 1) < 0)
     144                 :          0 :                 return (-1);
     145                 :            : 
     146                 :          0 :         bp = hp->buckets + PRI2BUCKET(hp, pri);
     147                 :            : #ifdef DEBUG
     148         [ #  # ]:          0 :         if (debug) {
     149                 :          0 :                 buckethead = bp;
     150                 :          0 :                 q1 = cq_debugbucket(hp, buckethead);
     151                 :            :         } else {
     152                 :          0 :                 buckethead = NULL;
     153                 :          0 :                 q1 = 0;
     154                 :            :         }
     155                 :            : #endif
     156         [ #  # ]:          0 :         if (BUCKETINUSE(bp)) {
     157                 :            :                 /* Allocate chained bucket */
     158         [ #  # ]:          0 :                 if (free_list) {
     159                 :          0 :                         bp2 = free_list;
     160                 :          0 :                         free_list = free_list->next;
     161                 :            :                 } else {
     162                 :          0 :                         bp2 = (struct cq_bucket *)malloc(sizeof(*bp2));
     163                 :          0 :                         memory_allocation += sizeof(*bp2);
     164         [ #  # ]:          0 :                         if (bp2 == NULL)
     165                 :          0 :                                 return (-1);
     166                 :            :                 }
     167         [ #  # ]:          0 :                 memset(bp2, 0, sizeof(*bp2));
     168         [ #  # ]:          0 :                 if (pri < bp->pri) {
     169                 :            :                         /* Insert new bucket at head of queue */
     170                 :          0 :                         *bp2 = *bp;
     171                 :          0 :                         bp->next = bp2;
     172                 :            :                 } else {
     173                 :            :                         /* Insert entry in order (fifo when pri's are equal) */
     174 [ #  # ][ #  # ]:          0 :                         while (bp->next != NULL && pri >= bp->next->pri)
     175                 :          0 :                                 bp = bp->next;
     176                 :          0 :                         bp2->next = bp->next;
     177                 :          0 :                         bp->next = bp2;
     178                 :          0 :                         bp = bp2;
     179                 :            :                 }
     180                 :            :         }
     181                 :          0 :         bp->pri = pri;
     182                 :          0 :         bp->cookie = cookie;
     183         [ #  # ]:          0 :         if (++hp->qlen > hp->max_qlen)
     184                 :          0 :                 hp->max_qlen = hp->qlen;
     185                 :            : #ifdef DEBUG
     186         [ #  # ]:          0 :         if (debug) {
     187                 :          0 :                 q2 = cq_debugbucket(hp, buckethead);
     188         [ #  # ]:          0 :                 if (q1 + 1 != q2) {
     189                 :          0 :                         fprintf(stderr, "enqueue length wrong\n");
     190                 :          0 :                         cq_dump(hp);
     191                 :          0 :                         abort();
     192                 :            :                 }
     193                 :            :         }
     194                 :            : #endif
     195                 :            : 
     196                 :            :         /* If new priority is old, we need to recalculate nextbucket */
     197 [ #  # ][ #  # ]:          0 :         if (hp->lastpri == 0.0 || hp->lastpri > pri) {
     198                 :          0 :                 hp->lastpri = pri;
     199                 :          0 :                 hp->nextbucket = PRI2BUCKET(hp, hp->lastpri);
     200                 :          0 :                 hp->buckettop = PRI2BUCKETTOP(hp, hp->lastpri);
     201                 :            :         }
     202                 :            : #ifdef notdef
     203                 :            :         if (debug)
     204                 :            :                 cq_debug(hp, 0);
     205                 :            : #endif
     206                 :          0 :         return (0);
     207                 :            : }
     208                 :            : 
     209                 :            : void *
     210                 :            : cq_dequeue(register struct cq_handle *hp, double pri)
     211                 :          0 : {
     212                 :            :         register int n;
     213                 :            :         register struct cq_bucket *bp, *bp2, *lowbp;
     214                 :            :         register void *cookie;
     215                 :            : 
     216                 :            : #ifdef DEBUG
     217         [ #  # ]:          0 :         if (debug > 1)
     218                 :          0 :                 fprintf(stderr, "cq_dequeue(%f)\n", pri);
     219                 :            : #endif
     220         [ #  # ]:          0 :         if (pri < hp->lastpri)
     221                 :            :                 /* For sure nothing to do. */
     222                 :          0 :                 return (NULL);
     223                 :            : 
     224                 :          0 :         lowbp = NULL;
     225         [ #  # ]:          0 :         for (n = hp->nbuckets, bp = hp->buckets + hp->nextbucket; n > 0; --n) {
     226                 :            :                 /* Check bucket if it contains an entry (in the current year) */
     227         [ #  # ]:          0 :                 if (BUCKETINUSE(bp)) {
     228         [ #  # ]:          0 :                         if (bp->pri < hp->buckettop) {
     229                 :            :                                 /* Check first entry in this bucket */
     230         [ #  # ]:          0 :                                 if (pri >= bp->pri) {
     231                 :          0 :                                         cookie = bp->cookie;
     232                 :          0 :                                         hp->lastpri = bp->pri;
     233                 :            :                                         /* Shouldn't nextbucket now point here?? */
     234                 :          0 :                                         hp->nextbucket = PRI2BUCKET(hp, hp->lastpri);
     235                 :          0 :                                         hp->buckettop = PRI2BUCKETTOP(hp, hp->lastpri);
     236         [ #  # ]:          0 :                                         if (bp->next == NULL) {
     237                 :            :                                                 /* Zero out first entry */
     238                 :          0 :                                                 bp->pri = 0.0;
     239                 :          0 :                                                 bp->cookie = NULL;
     240                 :            :                                         } else {
     241                 :            :                                                 /* Update 1st entry with next */
     242                 :          0 :                                                 bp2 = bp->next;
     243                 :          0 :                                                 *bp = *bp2;
     244                 :          0 :                                                 bp2->next = free_list;
     245                 :          0 :                                                 free_list = bp2;
     246                 :            :                                                 /* free(bp2); */
     247                 :            :                                         }
     248                 :          0 :                                         --hp->qlen;
     249         [ #  # ]:          0 :                                         if (hp->qlen < hp->lowmark)
     250                 :          0 :                                                 (void)cq_resize(hp, 0);
     251                 :            : #ifdef notdef
     252                 :            :                                         if (debug)
     253                 :            :                                                 cq_debug(hp, 0);
     254                 :            : #endif
     255                 :          0 :                                         return (cookie);
     256                 :            :                                 }
     257                 :            : 
     258                 :            :                                 /* The first entry is in the current year
     259                 :            :                                  * but comes after pri.  This means we're
     260                 :            :                                  * not going to find *any* subsequent entries
     261                 :            :                                  * that come before pri.  So we're done.
     262                 :            :                                  */
     263                 :          0 :                                 hp->lastpri = bp->pri;
     264                 :          0 :                                 hp->nextbucket = PRI2BUCKET(hp, hp->lastpri);
     265                 :          0 :                                 hp->buckettop = PRI2BUCKETTOP(hp, hp->lastpri);
     266                 :          0 :                                 return (NULL);
     267                 :            : #if 0
     268                 :            :                                 /* Search linked list */
     269                 :            :                                 /* Why is this necessary?  Since the list
     270                 :            :                                  * is sorted, and we already know that the
     271                 :            :                                  * first entry has too high a priority,
     272                 :            :                                  * none of the others can be ready to
     273                 :            :                                  * dequeue, right??
     274                 :            :                                  */
     275                 :            :                                 for (bp2 = bp; (bp3 = bp2->next) != NULL;
     276                 :            :                                     bp2 = bp3) {
     277                 :            :                                         /* Don't look past end of bucket */
     278                 :            :                                         if (bp3->pri >= hp->buckettop)
     279                 :            :                                                 break;
     280                 :            :                                         if (pri >= bp3->pri) {
     281                 :            :                                                 /* Unlink entry */
     282                 :            :                                                 cookie = bp3->cookie;
     283                 :            :                                                 hp->lastpri = bp->pri;
     284                 :            :                                                 bp2->next = bp3->next;
     285                 :            :                                                 free(bp3);
     286                 :            :                                                 memory_allocation -= sizeof(*bp3);
     287                 :            :                                                 --hp->qlen;
     288                 :            :                                                 if (hp->qlen < hp->lowmark)
     289                 :            :                                                         (void)cq_resize(hp, 0);
     290                 :            :                                                 return (cookie);
     291                 :            :                                         }
     292                 :            :                                 }
     293                 :            : #endif
     294                 :            :                         }
     295                 :            : 
     296                 :            :                         /* Keep track of lowest priority bucket */
     297 [ #  # ][ #  # ]:          0 :                         if (lowbp == NULL || lowbp->pri > bp->pri)
     298                 :          0 :                                 lowbp = bp;
     299                 :            :                 }
     300                 :            : 
     301                 :            :                 /* Step to next bucket */
     302                 :          0 :                 hp->buckettop += hp->bwidth;
     303                 :          0 :                 ++hp->nextbucket;
     304         [ #  # ]:          0 :                 if (hp->nextbucket < hp->nbuckets)
     305                 :          0 :                         ++bp;
     306                 :            :                 else {
     307                 :          0 :                         bp = hp->buckets;
     308                 :          0 :                         hp->nextbucket = 0;
     309                 :            :                 }
     310                 :            :         }
     311                 :            : 
     312                 :            :         /*
     313                 :            :          * If we got here, we checked all the buckets but came up
     314                 :            :          * empty. This can happen when the queued priorities are
     315                 :            :          * really sparse (e.g. when there is more than a year
     316                 :            :          * between two adjacent entries).
     317                 :            :          *
     318                 :            :          * If there was at least one bucket in use, check to see
     319                 :            :          * if it's the one we're looking for. Also, update nextbucket
     320                 :            :          * (and buckettop) with this bucket.
     321                 :            :          */
     322         [ #  # ]:          0 :         if (lowbp != NULL) {
     323                 :          0 :                 cookie = NULL;
     324                 :          0 :                 bp = lowbp;
     325         [ #  # ]:          0 :                 if (pri >= bp->pri) {
     326                 :          0 :                         cookie = bp->cookie;
     327         [ #  # ]:          0 :                         if (bp->next == NULL) {
     328                 :            :                                 /* Zero out first entry */
     329                 :          0 :                                 bp->pri = 0.0;
     330                 :          0 :                                 bp->cookie = NULL;
     331                 :            :                         } else {
     332                 :            :                                 /* Update 1st entry with next */
     333                 :          0 :                                 bp2 = bp->next;
     334                 :          0 :                                 *bp = *bp2;
     335                 :          0 :                                 bp2->next = free_list;
     336                 :          0 :                                 free_list = bp2;
     337                 :            :                                 /* free(bp2); */
     338                 :            :                         }
     339                 :          0 :                         --hp->qlen;
     340                 :            :                         /* If we resize, we don't need to update */
     341         [ #  # ]:          0 :                         if (hp->qlen < hp->lowmark) {
     342                 :          0 :                                 (void)cq_resize(hp, 0);
     343                 :          0 :                                 return (cookie);
     344                 :            :                         }
     345                 :            :                 }
     346                 :          0 :                 hp->lastpri = lowbp->pri;
     347                 :          0 :                 hp->nextbucket = PRI2BUCKET(hp, hp->lastpri);
     348                 :          0 :                 hp->buckettop = PRI2BUCKETTOP(hp, hp->lastpri);
     349         [ #  # ]:          0 :                 if (cookie != NULL)
     350                 :          0 :                         return (cookie);
     351                 :            :         }
     352                 :            : 
     353                 :            :         /* Checked all buckets */
     354                 :          0 :         return (NULL);
     355                 :            : }
     356                 :            : 
     357                 :            : void *
     358                 :            : cq_remove(register struct cq_handle *hp, register double pri,
     359                 :            :                             register void *cookie)
     360                 :          0 : {
     361                 :            :         register struct cq_bucket *bp, *bp2;
     362                 :            : 
     363                 :            :         /* The priority must be positive and the cookie non-null */
     364 [ #  # ][ #  # ]:          0 :         if (pri <= 0.0 || cookie == NULL)
     365                 :          0 :                 return (-0);
     366                 :            : 
     367                 :          0 :         bp = hp->buckets + PRI2BUCKET(hp, pri);
     368         [ #  # ]:          0 :         if (! BUCKETINUSE(bp))
     369                 :          0 :                 return (0);
     370                 :            : 
     371 [ #  # ][ #  # ]:          0 :         for ( bp2 = 0; bp && cookie != bp->cookie; bp = bp->next ) {
     372         [ #  # ]:          0 :                 if ( pri < bp->pri )
     373                 :          0 :                         return (0);
     374                 :          0 :                 bp2 = bp;
     375                 :            :                 }
     376                 :            : 
     377         [ #  # ]:          0 :         if ( ! bp )
     378                 :          0 :                 return (-0);
     379                 :            : 
     380                 :            :         /* Unlink entry */
     381         [ #  # ]:          0 :         if ( ! bp2 ) {
     382                 :            :                 /* Remove first element */
     383         [ #  # ]:          0 :                 if ( ! bp->next ) {
     384                 :            :                         /* Zero out first entry */
     385                 :          0 :                         bp->pri = 0.0;
     386                 :          0 :                         bp->cookie = NULL;
     387                 :            :                 } else {
     388                 :            :                         /* Update 1st entry with next */
     389                 :          0 :                         bp2 = bp->next;
     390                 :          0 :                         *bp = *bp2;
     391                 :          0 :                         bp2->next = free_list;
     392                 :          0 :                         free_list = bp2;
     393                 :            :                 }
     394                 :            :         }
     395                 :            :         else {
     396                 :            :                 /* Remove not-first element */
     397                 :          0 :                 bp2->next = bp->next;
     398                 :          0 :                 bp->next = free_list;
     399                 :          0 :                 free_list = bp;
     400                 :            :         }
     401                 :          0 :         --hp->qlen;
     402                 :            : 
     403         [ #  # ]:          0 :         if (hp->qlen < hp->lowmark)
     404                 :          0 :                 (void)cq_resize(hp, 0);
     405                 :            : 
     406                 :            :         /* buckettop etc. don't need to be updated, right? */
     407                 :          0 :         return cookie;
     408                 :            : }
     409                 :            : 
     410                 :            : int
     411                 :            : cq_size(struct cq_handle *hp)
     412                 :          0 : {
     413                 :          0 :         return hp->qlen;
     414                 :            : }
     415                 :            : 
     416                 :            : int
     417                 :            : cq_max_size(struct cq_handle *hp)
     418                 :          0 : {
     419                 :          0 :         return hp->max_qlen;
     420                 :            : }
     421                 :            : 
     422                 :            : /* Return without doing anything if we fail to allocate a new bucket array */
     423                 :            : static int
     424                 :            : cq_resize(register struct cq_handle *hp, register int grow)
     425                 :          0 : {
     426                 :            :         register int n, nbuckets, oldnbuckets;
     427                 :            :         register size_t size;
     428                 :            :         register struct cq_bucket *bp, *bp2, *buckets, *oldbuckets;
     429                 :            :         struct cq_handle savedhandle;
     430                 :            : 
     431         [ #  # ]:          0 :         if (hp->noresize)
     432                 :          0 :                 return (0);
     433                 :            : #ifdef DEBUG
     434         [ #  # ]:          0 :         if (debug)
     435                 :          0 :                 cq_debug(hp, 0);
     436                 :            : #endif
     437                 :            : 
     438                 :            :         /* Save old bucket array */
     439                 :          0 :         oldnbuckets = hp->nbuckets;
     440                 :          0 :         oldbuckets = hp->buckets;
     441                 :            : 
     442                 :            :         /* If no old buckets, we're initializing */
     443         [ #  # ]:          0 :         if (oldbuckets == NULL)
     444                 :          0 :                 nbuckets = 2;
     445         [ #  # ]:          0 :         else if (grow)
     446                 :          0 :                 nbuckets = oldnbuckets * 2;
     447                 :            :         else
     448                 :          0 :                 nbuckets = oldnbuckets / 2;
     449                 :            : 
     450                 :            :         /* XXX could check that nbuckets is a power of 2 */
     451                 :            : 
     452                 :          0 :         size = sizeof(*buckets) * nbuckets;
     453                 :          0 :         buckets = (struct cq_bucket *)malloc(size);
     454                 :          0 :         memory_allocation += size;
     455                 :            : 
     456         [ #  # ]:          0 :         if (buckets == NULL)
     457                 :          0 :                 return (-1);
     458         [ #  # ]:          0 :         memset(buckets, 0, size);
     459                 :            : 
     460                 :            :         /* Save a copy of the handle in case we have dynamic memory problems */
     461                 :          0 :         savedhandle = *hp;
     462                 :            : 
     463                 :            :         /* Install new bucket array */
     464                 :          0 :         hp->nbuckets = nbuckets;
     465                 :          0 :         hp->buckets = buckets;
     466                 :            : 
     467                 :            :         /* Initialize other parameters */
     468                 :          0 :         hp->himark = hp->nbuckets * 1.5;
     469                 :          0 :         hp->lowmark = (hp->nbuckets / 2) - 2;
     470                 :          0 :         hp->bwidth = hp->ysize / (double)hp->nbuckets;
     471                 :            : 
     472                 :            :         /* Tell cq_enqueue() to update nextbucket and buckettop */
     473                 :          0 :         hp->lastpri = 0.0;
     474                 :            : 
     475                 :            : #ifdef DEBUG
     476         [ #  # ]:          0 :         if (debug > 1)
     477                 :          0 :                 fprintf(stderr,
     478                 :            :                     "buckets 0x%lx, nbuckets %d, bwidth %f, buckettop %f\n",
     479                 :            :                     (u_long)hp->buckets,
     480                 :            :                     hp->nbuckets,
     481                 :            :                     hp->bwidth, hp->buckettop);
     482                 :            : #endif
     483                 :            : 
     484                 :            :         /* We're done if we were just initializing */
     485         [ #  # ]:          0 :         if (oldbuckets == NULL)
     486                 :          0 :                 return (0);
     487                 :            : 
     488                 :            :         /* Insert entries from old bucket array into new one */
     489                 :          0 :         ++hp->noresize;
     490                 :          0 :         hp->qlen = 0;
     491         [ #  # ]:          0 :         for (bp = oldbuckets, n = oldnbuckets; n > 0; --n, ++bp)
     492         [ #  # ]:          0 :                 if (BUCKETINUSE(bp))
     493         [ #  # ]:          0 :                         for (bp2 = bp; bp2 != NULL; bp2 = bp2->next) {
     494         [ #  # ]:          0 :                                 if (cq_enqueue(hp, bp2->pri, bp2->cookie) < 0) {
     495                 :            :                                         /* Bummer! */
     496                 :          0 :                                         *hp = savedhandle;
     497                 :            :                                         /* hp->resize restored */
     498                 :          0 :                                         cq_destroybuckets(buckets, nbuckets);
     499                 :          0 :                                         free(buckets);
     500                 :          0 :                                         memory_allocation -= size;
     501                 :          0 :                                         return (-1);
     502                 :            :                                 }
     503                 :            :                         }
     504                 :          0 :         --hp->noresize;
     505                 :            : 
     506                 :          0 :         cq_destroybuckets(oldbuckets, oldnbuckets);
     507                 :          0 :         free(oldbuckets);
     508                 :          0 :         memory_allocation -= sizeof(*buckets) * oldnbuckets;
     509                 :            : #ifdef DEBUG
     510         [ #  # ]:          0 :         if (debug)
     511                 :          0 :                 cq_debug(hp, 0);
     512                 :            : #endif
     513                 :          0 :         return (0);
     514                 :            : }
     515                 :            : 
     516                 :            : static void
     517                 :            : cq_destroybuckets(register struct cq_bucket *buckets, register int n)
     518                 :          0 : {
     519                 :            :         register struct cq_bucket *bp, *bp2, *bp3;
     520                 :            : 
     521         [ #  # ]:          0 :         for (bp = buckets; n > 0; --n, ++bp) {
     522                 :          0 :                 bp2 = bp->next;
     523         [ #  # ]:          0 :                 while (bp2 != NULL) {
     524                 :          0 :                         bp3 = bp2->next;
     525                 :          0 :                         bp2->next = free_list;
     526                 :          0 :                         free_list = bp2;
     527                 :            :                         /* free(bp2); */
     528                 :          0 :                         bp2 = bp3;
     529                 :            :                 }
     530                 :            :         }
     531                 :          0 : }
     532                 :            : 
     533                 :            : /* Destroy a calendar queue */
     534                 :            : void
     535                 :            : cq_destroy(register struct cq_handle *hp)
     536                 :          0 : {
     537                 :            : 
     538                 :          0 :         cq_destroybuckets(hp->buckets, hp->nbuckets);
     539         [ #  # ]:          0 :         while (free_list) {
     540                 :          0 :                 struct cq_bucket *next_free = free_list->next;
     541                 :          0 :                 free(free_list);
     542                 :          0 :                 free_list = next_free;
     543                 :            :         }
     544                 :          0 :         memory_allocation -= sizeof(struct cq_bucket) * hp->nbuckets;
     545                 :          0 :         free(hp->buckets);
     546                 :          0 :         free(hp);
     547                 :          0 :         memory_allocation -= sizeof(*hp);
     548                 :          0 : }
     549                 :            : 
     550                 :            : unsigned int
     551                 :            : cq_memory_allocation(void)
     552                 :          0 : {
     553                 :          0 :         return memory_allocation;
     554                 :            : }
     555                 :            : 
     556                 :            : #ifdef DEBUG
     557                 :            : static int
     558                 :            : cq_debugbucket(register struct cq_handle *hp,
     559                 :            :     register struct cq_bucket *buckets)
     560                 :          0 : {
     561                 :            :         register int qlen;
     562                 :            :         register struct cq_bucket *bp, *bp2;
     563                 :            :         double pri;
     564                 :            : 
     565                 :          0 :         qlen = 0;
     566                 :          0 :         pri = 0.0;
     567         [ #  # ]:          0 :         for (bp = buckets; bp != NULL; bp = bp->next) {
     568         [ #  # ]:          0 :                 if (BUCKETINUSE(bp)) {
     569                 :          0 :                         ++qlen;
     570                 :          0 :                         bp2 = hp->buckets + PRI2BUCKET(hp, bp->pri);
     571         [ #  # ]:          0 :                         if (bp2 != buckets) {
     572                 :          0 :                                 fprintf(stderr,
     573                 :            :                                     "%f in wrong bucket! (off by %d)\n",
     574                 :            :                                     bp->pri, bp2 - buckets);
     575                 :          0 :                                 cq_dump(hp);
     576                 :          0 :                                 abort();
     577                 :            :                         }
     578         [ #  # ]:          0 :                         if (bp->pri < pri) {
     579                 :          0 :                                 fprintf(stderr,
     580                 :            :                                     "bad pri order %f < %f (qlen %d)\n",
     581                 :            :                                     bp->pri, pri, qlen);
     582                 :          0 :                                 cq_dump(hp);
     583                 :          0 :                                 abort();
     584                 :            :                         }
     585                 :          0 :                         pri = bp->pri;
     586                 :            :                 }
     587                 :            :         }
     588                 :          0 :         return (qlen);
     589                 :            : }
     590                 :            : 
     591                 :            : void
     592                 :            : cq_debug(register struct cq_handle *hp, register int print)
     593                 :          0 : {
     594                 :            :         register int n, qlen, xnextbucket, nextbucket;
     595                 :            :         register struct cq_bucket *bp, *lowbp;
     596                 :            :         register double xbuckettop, buckettop;
     597                 :            : 
     598                 :          0 :         qlen = 0;
     599                 :          0 :         lowbp = NULL;
     600                 :          0 :         bp = hp->buckets + hp->nextbucket;
     601         [ #  # ]:          0 :         for (n = hp->nbuckets; n > 0; --n) {
     602 [ #  # ][ #  # ]:          0 :                 if (BUCKETINUSE(bp) && (lowbp == NULL || lowbp->pri > bp->pri))
                 [ #  # ]
     603                 :          0 :                         lowbp = bp;
     604                 :            : 
     605                 :          0 :                 qlen += cq_debugbucket(hp, bp);
     606                 :            : 
     607                 :            :                 /* Step to next bucket */
     608                 :          0 :                 ++bp;
     609         [ #  # ]:          0 :                 if (bp >= hp->buckets + hp->nbuckets)
     610                 :          0 :                         bp = hp->buckets;
     611                 :            :         }
     612                 :            : 
     613         [ #  # ]:          0 :         if (lowbp != NULL) {
     614                 :            :                 /* We expect lastpri gt or eq to the lowest queued priority */
     615         [ #  # ]:          0 :                 if (lowbp->pri < hp->lastpri) {
     616                 :          0 :                         fprintf(stderr, "lastpri wacked (%f < %f)\n",
     617                 :            :                             lowbp->pri, hp->lastpri);
     618                 :          0 :                         cq_dump(hp);
     619                 :          0 :                         abort();
     620                 :            :                 }
     621                 :            : 
     622                 :            :                 /* Must search for the next entry just as cq_dequeue() would */
     623                 :          0 :                 nextbucket = hp->nextbucket;
     624                 :          0 :                 buckettop = hp->buckettop;
     625                 :          0 :                 bp = hp->buckets + nextbucket;
     626         [ #  # ]:          0 :                 for (n = hp->nbuckets; n > 0; --n) {
     627 [ #  # ][ #  # ]:          0 :                         if (BUCKETINUSE(bp) && bp->pri < buckettop)
     628                 :          0 :                                 break;
     629                 :            : 
     630                 :            :                         /* Step to next bucket */
     631                 :          0 :                         ++bp;
     632                 :          0 :                         ++nextbucket;
     633                 :          0 :                         buckettop += hp->bwidth;
     634         [ #  # ]:          0 :                         if (bp >= hp->buckets + hp->nbuckets) {
     635                 :          0 :                                 bp = hp->buckets;
     636                 :          0 :                                 nextbucket = 0;
     637                 :            :                         }
     638                 :            :                 }
     639                 :            : 
     640                 :          0 :                 xnextbucket = PRI2BUCKET(hp, lowbp->pri);
     641         [ #  # ]:          0 :                 if (xnextbucket != nextbucket) {
     642                 :          0 :                         fprintf(stderr, "nextbucket wacked (%d != %d)\n",
     643                 :            :                              xnextbucket, nextbucket);
     644                 :          0 :                         cq_dump(hp);
     645                 :          0 :                         abort();
     646                 :            :                 }
     647                 :            : 
     648                 :          0 :                 xbuckettop = PRI2BUCKETTOP(hp, lowbp->pri);
     649         [ #  # ]:          0 :                 if (xbuckettop != buckettop) {
     650                 :          0 :                         fprintf(stderr, "buckettop wacked (%f != %f)\n",
     651                 :            :                             xbuckettop, buckettop);
     652                 :          0 :                         cq_dump(hp);
     653                 :          0 :                         abort();
     654                 :            :                 }
     655                 :            :         }
     656         [ #  # ]:          0 :         if (qlen != hp->qlen) {
     657                 :          0 :                 fprintf(stderr, "qlen wacked (%d != %d)\n", qlen, hp->qlen);
     658                 :          0 :                 cq_dump(hp);
     659                 :          0 :                 abort();
     660                 :            :         }
     661                 :          0 : }
     662                 :            : 
     663                 :            : void
     664                 :            : cq_dump(register struct cq_handle *hp)
     665                 :          0 : {
     666                 :            :         // ### FIXME
     667                 :            :         register struct cq_bucket *bp, *bp2;
     668                 :            :         register int n;
     669                 :            : 
     670                 :          0 :         fprintf(stderr,
     671                 :            :             "\ncq_dump(): nbucket %d, qlen %d, nextbucket %d, lastpri %f\n",
     672                 :            :             hp->nbuckets, hp->qlen, hp->nextbucket, hp->lastpri);
     673                 :          0 :         fprintf(stderr, "\tysize %f, bwidth %f, buckettop %f\n",
     674                 :            :             hp->ysize, hp->bwidth, hp->buckettop);
     675                 :            : 
     676                 :          0 :         bp = hp->buckets;
     677         [ #  # ]:          0 :         for (n = 0, bp = hp->buckets; n < hp->nbuckets; ++n, ++bp) {
     678         [ #  # ]:          0 :                 fprintf(stderr, "  %c %2d: %f (0x%lx)\n",
     679                 :            :                     (n == hp->nextbucket) ? '+' : ' ', n,
     680                 :            :                     bp->pri, (u_long)bp->cookie);
     681         [ #  # ]:          0 :                 for (bp2 = bp->next; bp2 != NULL; bp2 = bp2->next)
     682                 :          0 :                         fprintf(stderr, "        %f (0x%lx)\n",
     683                 :            :                             bp2->pri, (u_long)bp2->cookie);
     684                 :            :         }
     685                 :          0 : }
     686                 :            : #endif

Generated by: LCOV version 1.8