Esempio n. 1
0
static bool flush_incoming_que_on_wr_signal(rfc_slot_t *slot) {
  while (!list_is_empty(slot->incoming_queue)) {
    BT_HDR *p_buf = list_front(slot->incoming_queue);
    switch (send_data_to_app(slot->fd, p_buf)) {
      case SENT_NONE:
      case SENT_PARTIAL:
        //monitor the fd to get callback when app is ready to receive data
        btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_WR, slot->id);
        return true;

      case SENT_ALL:
        list_remove(slot->incoming_queue, p_buf);
        break;

      case SENT_FAILED:
        list_remove(slot->incoming_queue, p_buf);
        return false;
    }
  }

  //app is ready to receive data, tell stack to start the data flow
  //fix me: need a jv flow control api to serialize the call in stack
  APPL_TRACE_DEBUG("enable data flow, rfc_handle:0x%x, rfc_port_handle:0x%x, user_id:%d",
      slot->rfc_handle, slot->rfc_port_handle, slot->id);
  extern int PORT_FlowControl_MaxCredit(uint16_t handle, bool enable);
  PORT_FlowControl_MaxCredit(slot->rfc_port_handle, true);
  return true;
}
Esempio n. 2
0
File: search.c Progetto: Kirija/XPIR
void call_bind_rule( OBJECT * target_, OBJECT * boundname_ )
{
    LIST * const bind_rule = var_get( root_module(), constant_BINDRULE );
    if ( !list_empty( bind_rule ) )
    {
        OBJECT * target = object_copy( target_ );
        OBJECT * boundname = object_copy( boundname_ );
        if ( boundname && target )
        {
            /* Prepare the argument list. */
            FRAME frame[ 1 ];
            frame_init( frame );

            /* First argument is the target name. */
            lol_add( frame->args, list_new( target ) );

            lol_add( frame->args, list_new( boundname ) );
            if ( lol_get( frame->args, 1 ) )
            {
                OBJECT * rulename = list_front( bind_rule );
                list_free( evaluate_rule( bindrule( rulename, root_module() ), rulename, frame ) );
            }

            /* Clean up */
            frame_free( frame );
        }
        else
        {
            if ( boundname )
                object_free( boundname );
            if ( target )
                object_free( target );
        }
    }
}
Esempio n. 3
0
static int srunner_run_unchecked_setup (SRunner *sr, TCase *tc)
{
  TestResult *tr;
  List *l;
  Fixture *f;
  int rval = 1;

  set_fork_status(CK_NOFORK);

  l = tc->unch_sflst;

  for (list_front(l); !list_at_end(l); list_advance(l)) {
    send_ctx_info(CK_CTX_SETUP);
    f = list_val(l);
    f->fun();

    tr = receive_result_info_nofork (tc->name, "unchecked_setup", 0);

    if (tr->rtype != CK_PASS) {
      srunner_add_failure(sr, tr);
      rval = 0;
      break;
    }
    free(tr->file);
    free(tr->msg);
    free(tr);
  } 

  set_fork_status(srunner_fork_status(sr));
  return rval;
}
Esempio n. 4
0
static void srunner_iterate_tcase_tfuns (SRunner *sr, TCase *tc)
{
  List *tfl;
  TF *tfun;
  TestResult *tr = NULL;

  tfl = tc->tflst;
  
  for (list_front(tfl); !list_at_end (tfl); list_advance (tfl)) {
    int i;
    tfun = list_val (tfl);

    for (i = tfun->loop_start; i < tfun->loop_end; i++)
    {
      log_test_start (sr, tc, tfun);
      switch (srunner_fork_status(sr)) {
      case CK_FORK:
#ifdef _POSIX_VERSION
        tr = tcase_run_tfun_fork (sr, tc, tfun, i);
#else /* _POSIX_VERSION */
        eprintf("This version does not support fork", __FILE__, __LINE__);
#endif /* _POSIX_VERSION */
        break;
      case CK_NOFORK:
        tr = tcase_run_tfun_nofork (sr, tc, tfun, i);
        break;
      default:
        eprintf("Bad fork status in SRunner", __FILE__, __LINE__);
      }
      srunner_add_failure (sr, tr);
      log_test_end(sr, tr);
    }
  }
}  
void test__hash_multiset_find__hash_multiset_find_varg__libcstl_builtin_find(void** state)
{
    hash_multiset_t* pt_hash_multiset = _create_hash_multiset("list_t<int>");
    hash_multiset_iterator_t it_iter;
    list_t* plist = create_list(int);
    int i = 0;

    hash_multiset_init_ex(pt_hash_multiset, 0, _test__hash_private__libcstl_builtin_hash, NULL);
    list_init(plist);

    for(i = 0; i < 10; i++)
    {
        list_clear(plist);
        list_push_back(plist, i);
        hash_multiset_insert(pt_hash_multiset, plist);
    }

    list_clear(plist);
    list_push_back(plist, 6);
    it_iter = _hash_multiset_find(pt_hash_multiset, plist);
    assert_true(*(int*)list_front((list_t*)iterator_get_pointer(it_iter)) == 6);

    hash_multiset_destroy(pt_hash_multiset);
    list_destroy(plist);
}
Esempio n. 6
0
static TestResult * tcase_run_checked_setup (SRunner *sr, TCase *tc)
{
  TestResult *tr = NULL;
  List *l;
  Fixture *f;
  enum fork_status fstat = srunner_fork_status(sr);
  
  l = tc->ch_sflst;
  if (fstat == CK_FORK) {
    send_ctx_info(CK_CTX_SETUP);
  }
  
  for (list_front(l); !list_at_end(l); list_advance(l)) {
    if (fstat == CK_NOFORK) {
      send_ctx_info(CK_CTX_SETUP);
    }
    f = list_val(l);
    f->fun();

    /* Stop the setup and return the failure if nofork mode. */
    if (fstat == CK_NOFORK) {
      tr = receive_result_info_nofork (tc->name, "checked_setup", 0);
      if (tr->rtype != CK_PASS) {
        break;
      }

      free(tr->file);
      free(tr->msg);
      free(tr);
      tr = NULL;
    }
  }

  return tr;
}
Esempio n. 7
0
static const char * cache_name( void )
{
    static OBJECT * name = 0;
    if ( !name )
    {
        LIST * hcachevar = var_get( root_module(), constant_HCACHEFILE );

        if ( !list_empty( hcachevar ) )
        {
            TARGET * t = bindtarget( list_front( hcachevar ) );

            pushsettings( root_module(), t->settings );
            /* Do not expect the cache file to be generated, so pass 0 as the
             * third argument to search. Expect the location to be specified via
             * LOCATE, so pass 0 as the fourth arugment.
             */
            object_free( t->boundname );
            t->boundname = search( t->name, &t->time, 0, 0 );
            popsettings( root_module(), t->settings );

            name = object_copy( t->boundname );
        }
    }
    return name ? object_str( name ) : 0;
}
Esempio n. 8
0
LIST * list_pop_front( LIST * l )
{
    unsigned size = list_length( l );
    assert( size );
    --size;
    object_free( list_front( l ) );

    if ( size == 0 )
    {
        list_dealloc( l );
        return L0;
    }

    if ( ( ( size - 1 ) & size ) == 0 )
    {
        LIST * const nl = list_alloc( size );
        nl->impl.size = size;
        memcpy( list_begin( nl ), list_begin( l ) + 1, size * sizeof( OBJECT * )
            );
        list_dealloc( l );
        return nl;
    }

    l->impl.size = size;
    memmove( list_begin( l ), list_begin( l ) + 1, size * sizeof( OBJECT * ) );
    return l;
}
Esempio n. 9
0
/* Removes the front element from LIST and returns it.
   Undefined behavior if LIST is empty before removal. */
struct list_elem *
list_pop_front (struct list *list)
{
  struct list_elem *front = list_front (list);
  list_remove (front);
  return front;
}
Esempio n. 10
0
static void call_action_rule
(
    TARGET * target,
    int status,
    timing_info const * time,
    char const * executed_command,
    char const * command_output
)
{
    LIST * action_rule;

    pushsettings( root_module(), target->settings );
    action_rule = var_get( root_module(), constant_ACTION_RULE );
    popsettings( root_module(), target->settings );

    if ( !list_empty( action_rule ) )
    {
        /* rule action-rule (
            args * :
            target :
            command status start end user system :
            output ? ) */

        /* Prepare the argument list. */
        FRAME frame[ 1 ];
        OBJECT * rulename = list_front( action_rule );
        frame_init( frame );

        /* args * :: $(__ACTION_RULE__[2-]) */
        lol_add( frame->args, list_copy_range( action_rule, list_next(
            list_begin( action_rule ) ), list_end( action_rule ) ) );

        /* target :: the name of the target */
        lol_add( frame->args, list_new( object_copy( target->name ) ) );

        /* command status start end user system :: info about the action command
         */
        lol_add( frame->args,
            list_push_back( list_push_back( list_push_back( list_push_back( list_push_back( list_new(
                object_new( executed_command ) ),
                outf_int( status ) ),
                outf_time( &time->start ) ),
                outf_time( &time->end ) ),
                outf_double( time->user ) ),
                outf_double( time->system ) ) );

        /* output ? :: the output of the action command */
        if ( command_output )
            lol_add( frame->args, list_new( object_new( command_output ) ) );
        else
            lol_add( frame->args, L0 );

        /* Call the rule. */
        evaluate_rule( bindrule( rulename, root_module() ), rulename, frame );

        /* Clean up. */
        frame_free( frame );
    }
}
Esempio n. 11
0
/* Removes the front element from LIST and returns it.
   Undefined behavior if LIST is empty before removal. */
struct list_elem *
list_pop_front (struct list *list)
{
  struct list_elem *front = list_front (list);
  list_remove (front);
  front->magic = BAD_LIST_ELEM_MAGIC__;
  return front;
}
Esempio n. 12
0
void
thread_cleanup_and_exit (int status) 
{
  printf ("%s: exit(%d)\n", thread_name (), status);
  /* close all open file descriptors */
  struct thread *t = thread_current ();
 
  struct list_elem *e;

  /* close all the files opened and
     free spaces allocated for the file list */
  while (!list_empty (&t->file_list))
    {
      e = list_pop_back (&t->file_list);
      struct file_elem *f_elem = list_entry (e, struct file_elem, elem);
      file_close (f_elem->file);
      free (f_elem);
    }

  /* free waited_children_list and children_list */
  while (!list_empty (&t->children_list))
    {
      e = list_pop_back (&t->children_list);
      struct child_elem *c_elem = list_entry (e, struct child_elem, elem);
      // free children from the global exit_list
      free_thread_from_exit_list (c_elem->pid);
      free (c_elem);
    }
  while (!list_empty (&t->waited_children_list))
    {
      e = list_pop_back (&t->waited_children_list);
      struct wait_child_elem *w_elem = list_entry (e, struct wait_child_elem, elem);
      free (w_elem);
    }

  add_thread_to_exited_list (t->tid, status);
  
  /* allow file write to executable */
  if (t->exec_file) 
    {
      file_allow_write (t->exec_file);
      file_close (t->exec_file);
    }

  /* release all the locks that have not already been released */
  while (!list_empty (&t->acquired_locks))
    {
      struct list_elem *e = list_front (&t->acquired_locks);
      struct lock *l = list_entry (e, struct lock, elem);
      lock_release (l);
    }
  /* wake parent up if its waiting on it */
  struct thread *parent = get_thread (thread_current ()->parent_id);
  if (parent)  {
    sema_up (&parent->waiting_on_child_exit_sema);
  }
  thread_exit ();
}
Esempio n. 13
0
void list_apply (List *lp, void (*fp) (void *))
{
  if (lp == NULL || fp == NULL)
    return;

  for (list_front(lp); !list_at_end(lp); list_advance(lp))
    fp (list_val(lp));
  
}
Esempio n. 14
0
list* search_breadth_first(void* state,
                           void* state_world,
                           search_is_goal state_goal_func,
                           search_gen_successors state_gen_func,
                           search_link_parent state_link_func,
                           search_goal_backtrace state_back_func,
                           hash_func state_hash_alg,
                           generic_comp state_comp_func,
                           generic_cpy state_copy_func,
                           generic_op state_free_func) {
    int found;
    void* current_state, *successor_state;
    list* state_queue, *successor_list, *path;
    hash_table* state_closed_set;

    state_queue = list_create(NULL,
                              NULL,
                              state_free_func);

    state_closed_set = hash_table_create(89,
                                         .75,
                                         state_hash_alg,
                                         state_comp_func,
                                         state_copy_func,
                                         state_free_func);
    current_state = state;
    list_push_front(state_queue, current_state);
    hash_table_insert(state_closed_set, current_state, 0);
    path = NULL;
    found = 0;
    while(!list_is_empty(state_queue) && !found) {
        current_state = list_back(state_queue);
        list_deque(state_queue);
        if(state_goal_func(current_state, state_world)) {
            current_state = state_copy_func(current_state);
            path = state_back_func(current_state);
            found = 1;
        } else {
            successor_list = state_gen_func(current_state, state_world);
            while(!list_is_empty(successor_list)) {
                successor_state = list_front(successor_list);
                if(!hash_table_contains(state_closed_set, successor_state)) {
                    state_link_func(successor_state, current_state);
                    hash_table_insert(state_closed_set, successor_state, 0);
                    list_push_front(state_queue, successor_state);
                    list_pop(successor_list);
                } else {
                    list_remove_front(successor_list);
                }
            }
            list_kill(successor_list);
        }
    }
    hash_table_kill(state_closed_set);
    list_dissolve(state_queue);
    return path;
}
Esempio n. 15
0
// NOTE: must be called with monitor lock.
static void reschedule_root_alarm(void) {
  bool timer_was_set = timer_set;
  assert(alarms != NULL);

  // If used in a zeroed state, disarms the timer
  struct itimerspec wakeup_time;
  memset(&wakeup_time, 0, sizeof(wakeup_time));

  if (list_is_empty(alarms))
    goto done;

  alarm_t *next = list_front(alarms);
  int64_t next_expiration = next->deadline - now();
  if (next_expiration < TIMER_INTERVAL_FOR_WAKELOCK_IN_MS) {
    if (!timer_set) {
      int status = bt_os_callouts->acquire_wake_lock(WAKE_LOCK_ID);
      if (status != BT_STATUS_SUCCESS) {
        LOG_ERROR("%s unable to acquire wake lock: %d", __func__, status);
        goto done;
      }
    }

    wakeup_time.it_value.tv_sec = (next->deadline / 1000);
    wakeup_time.it_value.tv_nsec = (next->deadline % 1000) * 1000000LL;
  } else {
    if (!bt_os_callouts->set_wake_alarm(next_expiration, true, timer_callback, NULL))
      LOG_ERROR("%s unable to set wake alarm for %" PRId64 "ms.", __func__, next_expiration);
  }

done:
  timer_set = wakeup_time.it_value.tv_sec != 0 || wakeup_time.it_value.tv_nsec != 0;
  if (timer_was_set && !timer_set) {
    bt_os_callouts->release_wake_lock(WAKE_LOCK_ID);
  }

  if (timer_settime(timer, TIMER_ABSTIME, &wakeup_time, NULL) == -1)
    LOG_ERROR("%s unable to set timer: %s", __func__, strerror(errno));

  // If next expiration was in the past (e.g. short timer that got context switched)
  // then the timer might have diarmed itself. Detect this case and work around it
  // by manually signalling the |alarm_expired| semaphore.
  //
  // It is possible that the timer was actually super short (a few milliseconds)
  // and the timer expired normally before we called |timer_gettime|. Worst case,
  // |alarm_expired| is signaled twice for that alarm. Nothing bad should happen in
  // that case though since the callback dispatch function checks to make sure the
  // timer at the head of the list actually expired.
  if (timer_set) {
    struct itimerspec time_to_expire;
    timer_gettime(timer, &time_to_expire);
    if (time_to_expire.it_value.tv_sec == 0 && time_to_expire.it_value.tv_nsec == 0) {
      LOG_ERROR("%s alarm expiration too close for posix timers, switching to guns", __func__);
      semaphore_post(alarm_expired);
    }
  }
}
Esempio n. 16
0
File: llist.c Progetto: xorver/mikro
List *list_push_front(List *l, void *data)
{
  l = list_front(l);
  l->prev = (List *) malloc(sizeof(List));
  l->prev->data = data;
  l->prev->next = l;
  l->prev->prev = 0;

  return l->prev;
}
Esempio n. 17
0
/**
 * Access queue front data.
 */
void* queue_front(const queue_t* cpque_queue)
{
    assert(cpque_queue != NULL);

#ifdef CSTL_QUEUE_LIST_SEQUENCE
    return list_front(&cpque_queue->_t_sequence);
#else
    return deque_front(&cpque_queue->_t_sequence);
#endif
}
Esempio n. 18
0
static void srunner_run_teardown (List *l)
{
  Fixture *f;
  
  for (list_front(l); !list_at_end(l); list_advance(l)) {
    f = list_val(l);
    send_ctx_info(CK_CTX_TEARDOWN);
    f->fun ();
  }
}
Esempio n. 19
0
void
headers( TARGET * t )
{
    LIST   * hdrscan;
    LIST   * hdrrule;
	#ifndef OPT_HEADER_CACHE_EXT
    LIST   * headlist = L0;
	#endif
    regexp * re[ MAXINC ];
    int rec = 0;
    LISTITER iter, end;

    hdrscan = var_get( root_module(), constant_HDRSCAN );
    if ( list_empty( hdrscan ) )
        return;

    hdrrule = var_get( root_module(), constant_HDRRULE );
    if ( list_empty( hdrrule ) )
        return;

    if ( DEBUG_HEADER )
        printf( "header scan %s\n", object_str( t->name ) );

    /* Compile all regular expressions in HDRSCAN */
    iter = list_begin( hdrscan ), end = list_end( hdrscan );
    for ( ; ( rec < MAXINC ) && iter != end; iter = list_next( iter ) )
    {
        re[ rec++ ] = regex_compile( list_item( iter ) );
    }

    /* Doctor up call to HDRRULE rule */
    /* Call headers1() to get LIST of included files. */
    {
        FRAME   frame[1];
        frame_init( frame );
        lol_add( frame->args, list_new( object_copy( t->name ) ) );
#ifdef OPT_HEADER_CACHE_EXT
        lol_add( frame->args, hcache( t, rec, re, hdrscan ) );
#else
        lol_add( frame->args, headers1( headlist, t->boundname, rec, re ) );
#endif

        if ( lol_get( frame->args, 1 ) )
        {
            /* The third argument to HDRRULE is the bound name of
             * $(<) */
            lol_add( frame->args, list_new( object_copy( t->boundname ) ) );

            list_free( evaluate_rule( list_front( hdrrule ), frame ) );
        }

        /* Clean up. */
        frame_free( frame );
    }
}
Esempio n. 20
0
static void write_handler(nl_event_t *ev)
{
    nl_socket_t         *sock;
    nl_stream_t         *s;
    nl_buf_t            *buf;
    int                 rc;

    sock = ev->data;
    log_trace("#%d write_handler", sock->fd);
    s = sock->data;

    while (!list_empty(s->tosend)) {
        buf = (nl_buf_t *)list_front(s->tosend);
        rc = nl_send(sock, buf->buf, buf->len);
        if (rc >= 0) {
            if ((size_t)rc < buf->len) {
                /* accurate pending bytes */
                buf->len -= rc;
                memmove(buf->buf, buf->buf + rc, buf->len);
                if (s->cbs.on_sent) {
                    s->cbs.on_sent(s, rc);
                }
            }
            else {
                /* accurate pending bytes */
                list_pop_front(s->tosend);
                if (s->cbs.on_sent) {
                    s->cbs.on_sent(s, rc);
                }
                free(buf->buf);
            }
        }
        else { /* rc < 0 */
            if (!sock->error) {
                return;
            }
            else {
                s->error = 1;
                if (s->closing_ev.timer_set) {
                    nl_event_del_timer(&s->closing_ev);
                }
                nl_stream_close(s);
                return;
            }
        }
    }

    /* tosend is empty */
    nl_event_del(&s->sock.wev);
    if (s->closing_ev.timer_set) {
        nl_event_del_timer(&s->closing_ev);
        nl_stream_close(s);
    }
}
Esempio n. 21
0
TEST_F(ListTest, test_list_front) {
  int x[] = { 1, 2, 3, 4, 5 };
  list_t *list = list_new(NULL);

  for (size_t i = 0; i < ARRAY_SIZE(x); ++i)
    list_append(list, &x[i]);

  EXPECT_EQ(list_front(list), &x[0]);

  list_free(list);
}
Esempio n. 22
0
static void srunner_send_evt (SRunner *sr, void *obj, enum cl_event evt)
{
  List *l;
  Log *lg;
  l = sr->loglst;
  for (list_front(l); !list_at_end(l); list_advance(l)) {
    lg = list_val(l);
    fflush(lg->lfile);
    lg->lfun (sr, lg->lfile, lg->mode, obj, evt);
    fflush(lg->lfile);
  }
}
Esempio n. 23
0
File: server.c Progetto: kaye64/gem
/**
 * Properly frees a server_t
 */
static void server_free(server_t* server)
{
	/* force a cleanup of each client */
	while (!list_empty(&server->client_list)) {
		list_node_t* node = list_front(&server->client_list);
		client_t* client = container_of(node, client_t, node);
		server_client_cleanup(server, client);
	}

	object_free(&server->client_list);
	free(server->buffer);
}
Esempio n. 24
0
static int cache_maxage( void )
{
    int age = 100;
    LIST * var = var_get( root_module(), constant_HCACHEMAXAGE );
    if ( !list_empty( var ) )
    {
        age = atoi( object_str( list_front( var ) ) );
        if ( age < 0 )
            age = 0;
    }
    return age;
}
Esempio n. 25
0
static void suite_free (Suite *s)
{
  List *l;
  if (s == NULL)
    return;
  l = s->tclst;
  for (list_front(l); !list_at_end(l); list_advance (l)) {
    tcase_free (list_val(l));
  }
  list_free (s->tclst);
  free(s);
}
Esempio n. 26
0
static void srunner_fprint_results (FILE *file, SRunner *sr,
				    enum print_output print_mode)
{
  List *resultlst;
  
  resultlst = sr->resultlst;
  
  for (list_front(resultlst); !list_at_end(resultlst); list_advance(resultlst)) {
    TestResult *tr = list_val(resultlst);
    tr_fprint (file, tr, print_mode);
  }
  return;
}
Esempio n. 27
0
struct bstree *parser_analisar_tokens(list **lista)
{
	struct lnode *no = list_front(*lista);

	tokens = lista;
	if (list_isempty(*lista)) {
		err("Lista de tokens vazia: nada para analisar.");
		exit(1);
	}
	parser_montar_arvore(no);
	debug("\033[1mÁrvore dos lexemas montada.\033[0m");
	return tree;
}
Esempio n. 28
0
/* push the next MAKE1C state after a command is run. */
static void push_cmds( CMDLIST * cmds, int status )
{
    CMDLIST * cmd_iter;
    for( cmd_iter = cmds; cmd_iter; cmd_iter = cmd_iter->next )
    {
        if ( cmd_iter->iscmd )
        {
            CMD * next_cmd = cmd_iter->impl.cmd;
            /* Propagate the command status. */
            if ( next_cmd->status < status )
                next_cmd->status = status;
            if ( --next_cmd->asynccnt == 0 )
            {
                /* Select the first target associated with the action.
                 * This is safe because sibling CMDs cannot have targets
                 * in common.
                 */
                TARGET * first_target = bindtarget( list_front( lol_get( &next_cmd->args, 0 ) ) );
                first_target->cmds = (char *)next_cmd;
                push_state( &state_stack, first_target, NULL, T_STATE_MAKE1C );
            }
            else if ( DEBUG_EXECCMD )
            {
                TARGET * first_target = bindtarget( list_front( lol_get( &next_cmd->args, 0 ) ) );
                printf( "Delaying %s %s: %d targets not ready\n", object_str( next_cmd->rule->name ), object_str( first_target->boundname ), next_cmd->asynccnt );
            }
        }
        else
        {
            /* This is a target that we're finished updating */
            TARGET * updated_target = cmd_iter->impl.t;
            if ( updated_target->status < status )
                updated_target->status = status;
            updated_target->cmds = NULL;
            push_state( &state_stack, updated_target, NULL, T_STATE_MAKE1C );
        }
    }
}
void *fixed_queue_dequeue(fixed_queue_t *queue) {
  assert(queue != NULL);

  semaphore_wait(queue->dequeue_sem);

  pthread_mutex_lock(&queue->lock);
  void *ret = list_front(queue->list);
  list_remove(queue->list, ret);
  pthread_mutex_unlock(&queue->lock);

  semaphore_post(queue->enqueue_sem);

  return ret;
}
Esempio n. 30
0
/* 
 * Typically, called after grow(...) or shrink(...).
 * Relocates all hashtable items from source array to the new array
 * in the hashtable.
 */
static
void
rehash(struct hashtable* h,
       struct list** source_array, unsigned int source_size)
{
    unsigned int i;
    struct list* chain;
    struct kv_pair* item;
    for (i = 0; i < source_size; ++i) {
        chain = source_array[i];
        assert(chain != NULL);
        if (list_getsize(chain) > 0) {
            item = (struct kv_pair*)list_front(chain);
            while (item) {
                hashtable_add(h, item->key, item->keylen, item->val);
                list_pop_front(chain);
                free(item);
                item = (struct kv_pair*)list_front(chain);
            }
            assert(list_getsize(chain) == 0);
        }
    }
}