Merge branch 'master' into merge6
Signed-off-by: Martin Bremmer <martin.bremmer@adlinktech.com>
This commit is contained in:
		
						commit
						660d495746
					
				
					 124 changed files with 5049 additions and 1672 deletions
				
			
		| 
						 | 
				
			
			@ -184,6 +184,19 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
 | 
			
		|||
      endif()
 | 
			
		||||
      set(system_exists FALSE)
 | 
			
		||||
 | 
			
		||||
      # Headers that must remain private but are required by other runtime
 | 
			
		||||
      # source files must be located in src/<feature>/dds/ddsrt.
 | 
			
		||||
      if(IS_DIRECTORY "${source_path}/${feature}/include")
 | 
			
		||||
        file(GLOB_RECURSE
 | 
			
		||||
               files
 | 
			
		||||
             CONFIGURE_DEPENDS
 | 
			
		||||
               "${source_path}/${feature}/include/*.h")
 | 
			
		||||
        list(APPEND headers ${files})
 | 
			
		||||
        target_include_directories(
 | 
			
		||||
          ddsrt INTERFACE
 | 
			
		||||
            "$<BUILD_INTERFACE:${source_path}/${feature}/include/>")
 | 
			
		||||
      endif()
 | 
			
		||||
 | 
			
		||||
      # Allow custom implementations for a feature. e.g. lwip as opposed to
 | 
			
		||||
      # windows or posix.
 | 
			
		||||
      set(_system_name "${system_name}")
 | 
			
		||||
| 
						 | 
				
			
			@ -192,18 +205,6 @@ foreach(feature atomics cdtors environ heap ifaddrs random rusage
 | 
			
		|||
      endif()
 | 
			
		||||
 | 
			
		||||
      foreach(system ${_system_name} posix)
 | 
			
		||||
        # Headers that must remain private but are required by other runtime
 | 
			
		||||
        # source files must be located in src/<feature>/dds/ddsrt.
 | 
			
		||||
        if(IS_DIRECTORY "${source_path}/${feature}/include")
 | 
			
		||||
          file(GLOB_RECURSE
 | 
			
		||||
                 files
 | 
			
		||||
               CONFIGURE_DEPENDS
 | 
			
		||||
                 "${source_path}/${feature}/include/*.h")
 | 
			
		||||
          list(APPEND headers ${files})
 | 
			
		||||
          target_include_directories(
 | 
			
		||||
            ddsrt INTERFACE
 | 
			
		||||
              "$<BUILD_INTERFACE:${source_path}/${feature}/include/>")
 | 
			
		||||
        endif()
 | 
			
		||||
        if(IS_DIRECTORY "${source_path}/${feature}/${system}")
 | 
			
		||||
          file(GLOB_RECURSE
 | 
			
		||||
                 files
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,4 +84,5 @@ inline int64_t ddsrt_bswap8 (int64_t x)
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* DDSRT_BSWAP_H */
 | 
			
		||||
#endif /* DDSRT_BSWAP_H */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,6 +62,9 @@ typedef int64_t dds_duration_t;
 | 
			
		|||
/** @name Invalid time value for assigning to time output when something goes wrong */
 | 
			
		||||
#define DDS_TIME_INVALID ((dds_time_t) INT64_MIN)
 | 
			
		||||
 | 
			
		||||
/** @name Invalid duration value */
 | 
			
		||||
#define DDS_DURATION_INVALID ((dds_duration_t) INT64_MIN)
 | 
			
		||||
 | 
			
		||||
/** @name Macro definition for time conversion to nanoseconds
 | 
			
		||||
  @{**/
 | 
			
		||||
#define DDS_SECS(n) ((n) * DDS_NSECS_IN_SEC)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,10 +42,10 @@ static char *expand_env (const char *name, char op, const char *alt, expand_fn e
 | 
			
		|||
    if ((ret = ddsrt_getenv (name, &env)) == DDS_RETCODE_OK) {
 | 
			
		||||
        /* ok */
 | 
			
		||||
    } else if (strcmp (name, "$") == 0 || strcmp (name, "CYCLONEDDS_PID") == 0) {
 | 
			
		||||
        snprintf (idstr, sizeof (idstr), "%"PRIdPID, ddsrt_getpid ());
 | 
			
		||||
        (void) snprintf (idstr, sizeof (idstr), "%"PRIdPID, ddsrt_getpid ());
 | 
			
		||||
        env = idstr;
 | 
			
		||||
    } else if (strcmp (name, "CYCLONEDDS_DOMAIN_ID") == 0 && domid != UINT32_MAX) {
 | 
			
		||||
        snprintf (idstr, sizeof (idstr), "%"PRIu32, domid);
 | 
			
		||||
        (void) snprintf (idstr, sizeof (idstr), "%"PRIu32, domid);
 | 
			
		||||
        env = idstr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,10 +84,12 @@ static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t
 | 
			
		|||
  uint32_t hopinfo = rt->buckets[bucket].hopinfo;
 | 
			
		||||
  uint32_t idx;
 | 
			
		||||
  for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
 | 
			
		||||
    const uint32_t bidx = (bucket + idx) & idxmask;
 | 
			
		||||
    void *data = rt->buckets[bidx].data;
 | 
			
		||||
    if (data && rt->equals (data, template))
 | 
			
		||||
      return data;
 | 
			
		||||
    if (hopinfo & 1) {
 | 
			
		||||
      const uint32_t bidx = (bucket + idx) & idxmask;
 | 
			
		||||
      void *data = rt->buckets[bidx].data;
 | 
			
		||||
      if (data && rt->equals (data, template))
 | 
			
		||||
        return data;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -453,10 +455,12 @@ static void *ddsrt_chh_lookup_internal (struct ddsrt_chh_bucket_array const * co
 | 
			
		|||
        ddsrt_atomic_fence_ldld ();
 | 
			
		||||
        hopinfo = ddsrt_atomic_ld32 (&bs[bucket].hopinfo);
 | 
			
		||||
        for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) {
 | 
			
		||||
            const uint32_t bidx = (bucket + idx) & idxmask;
 | 
			
		||||
            void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data);
 | 
			
		||||
            if (ddsrt_chh_data_valid_p (data) && equals (data, template)) {
 | 
			
		||||
                return data;
 | 
			
		||||
            if (hopinfo & 1) {
 | 
			
		||||
                const uint32_t bidx = (bucket + idx) & idxmask;
 | 
			
		||||
                void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data);
 | 
			
		||||
                if (ddsrt_chh_data_valid_p (data) && equals (data, template)) {
 | 
			
		||||
                    return data;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        ddsrt_atomic_fence_ldld ();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,7 +94,7 @@ static enum ddsrt_iftype guess_iftype (const struct ifaddrs *sys_ifa)
 | 
			
		|||
  struct ifmediareq ifmr;
 | 
			
		||||
  enum ddsrt_iftype type;
 | 
			
		||||
  memset (&ifmr, 0, sizeof (ifmr));
 | 
			
		||||
  ddsrt_strlcpy (ifmr.ifm_name, sys_ifa->ifa_name, sizeof (ifmr.ifm_name));
 | 
			
		||||
  (void) ddsrt_strlcpy (ifmr.ifm_name, sys_ifa->ifa_name, sizeof (ifmr.ifm_name));
 | 
			
		||||
  if (ioctl (sock, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0)
 | 
			
		||||
  {
 | 
			
		||||
    type = DDSRT_IFTYPE_UNKNOWN;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ static void default_sink (void *ptr, const dds_log_data_t *data)
 | 
			
		|||
{
 | 
			
		||||
  if (ptr)
 | 
			
		||||
  {
 | 
			
		||||
    fwrite (data->message - data->hdrsize, 1, data->hdrsize + data->size + 1, (FILE *) ptr);
 | 
			
		||||
    (void) fwrite (data->message - data->hdrsize, 1, data->hdrsize + data->size + 1, (FILE *) ptr);
 | 
			
		||||
    fflush ((FILE *) ptr);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -203,8 +203,8 @@ ddsrt_proc_create(
 | 
			
		|||
    if (write(exec_fds[1], &exec_err, sizeof(int)) < (ssize_t)sizeof(int)) {
 | 
			
		||||
      DDS_ERROR("Could not write proc error pipe.\n");
 | 
			
		||||
    }
 | 
			
		||||
    close(exec_fds[1]);
 | 
			
		||||
    close(exec_fds[0]);
 | 
			
		||||
    (void) close(exec_fds[1]);
 | 
			
		||||
    (void) close(exec_fds[0]);
 | 
			
		||||
    ddsrt_free(exec_argv);
 | 
			
		||||
    _exit(1);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -214,7 +214,7 @@ ddsrt_proc_create(
 | 
			
		|||
 | 
			
		||||
    /* Get execv result. */
 | 
			
		||||
    rv = DDS_RETCODE_ERROR;
 | 
			
		||||
    close(exec_fds[1]);
 | 
			
		||||
    (void) close(exec_fds[1]);
 | 
			
		||||
    nr = read(exec_fds[0], &exec_err, sizeof(int));
 | 
			
		||||
    if (nr == 0) {
 | 
			
		||||
      /* Pipe closed by successful execv. */
 | 
			
		||||
| 
						 | 
				
			
			@ -228,14 +228,14 @@ ddsrt_proc_create(
 | 
			
		|||
        rv = DDS_RETCODE_NOT_ALLOWED;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    close(exec_fds[0]);
 | 
			
		||||
    (void) close(exec_fds[0]);
 | 
			
		||||
 | 
			
		||||
    if (rv == DDS_RETCODE_OK) {
 | 
			
		||||
      /* Remember child pid. */
 | 
			
		||||
      *pid = spawn;
 | 
			
		||||
    } else {
 | 
			
		||||
      /* Remove the failed fork pid from the system list. */
 | 
			
		||||
      waitpid(spawn, NULL, 0);
 | 
			
		||||
      (void) waitpid(spawn, NULL, 0);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -244,8 +244,8 @@ ddsrt_proc_create(
 | 
			
		|||
 | 
			
		||||
fail_fork:
 | 
			
		||||
fail_fctl:
 | 
			
		||||
  close(exec_fds[0]);
 | 
			
		||||
  close(exec_fds[1]);
 | 
			
		||||
  (void) close(exec_fds[0]);
 | 
			
		||||
  (void) close(exec_fds[1]);
 | 
			
		||||
fail_pipe:
 | 
			
		||||
  ddsrt_free(exec_argv);
 | 
			
		||||
  return rv;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,7 +109,7 @@ ddsrt_getrusage_anythread (
 | 
			
		|||
    return DDS_RETCODE_ERROR;
 | 
			
		||||
  if ((fp = fopen (file, "r")) == NULL)
 | 
			
		||||
    return DDS_RETCODE_NOT_FOUND;
 | 
			
		||||
  enum { ERROR, READ_HEADING, SKIP_TO_EOL, READ_VCSW, READ_IVCSW } state = READ_HEADING;
 | 
			
		||||
  enum { ERROR = 1, READ_HEADING, SKIP_TO_EOL, READ_VCSW, READ_IVCSW } state = READ_HEADING;
 | 
			
		||||
  savepos = 0;
 | 
			
		||||
  while (state != ERROR && (c = fgetc (fp)) != EOF)
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -126,7 +126,7 @@ ddsrt_thread_setname(const char *__restrict name)
 | 
			
		|||
  /* Thread names are limited to 16 bytes on Linux. ERANGE is returned if the
 | 
			
		||||
     name exceeds the limit, so silently truncate. */
 | 
			
		||||
  char buf[MAXTHREADNAMESIZE + 1] = "";
 | 
			
		||||
  ddsrt_strlcpy(buf, name, sizeof(buf));
 | 
			
		||||
  (void)ddsrt_strlcpy(buf, name, sizeof(buf));
 | 
			
		||||
  (void)pthread_setname_np(pthread_self(), name);
 | 
			
		||||
#elif defined(__APPLE__)
 | 
			
		||||
  (void)pthread_setname_np(name);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -313,7 +313,7 @@ ddsrt_thread_setname(
 | 
			
		|||
    }
 | 
			
		||||
#pragma warning(pop)
 | 
			
		||||
  }
 | 
			
		||||
  ddsrt_strlcpy (thread_name, name, sizeof (thread_name));
 | 
			
		||||
  (void)ddsrt_strlcpy (thread_name, name, sizeof (thread_name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dds_return_t
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,7 +36,7 @@ struct ddsrt_xmlp_state {
 | 
			
		|||
    size_t cbufmax; /* allocated size of cbuf (cbufn <= cbufmax) */
 | 
			
		||||
    size_t cbufmark; /* NORMARKER or marker position (cbufmark <= cbufp) for rewinding */
 | 
			
		||||
    int eof; /* fake EOF (for treating missing close tags as EOF) */
 | 
			
		||||
    char *cbuf; /* parser input buffer */
 | 
			
		||||
    unsigned char *cbuf; /* parser input buffer */
 | 
			
		||||
    FILE *fp; /* file to refill cbuf from, or NULL if parsing a string */
 | 
			
		||||
    int line; /* current line number */
 | 
			
		||||
    int prevline; /* line number at last token */
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +147,7 @@ struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg,
 | 
			
		|||
    st = ddsrt_malloc (sizeof (*st));
 | 
			
		||||
    st->cbufn = strlen (string);
 | 
			
		||||
    st->cbufmax = st->cbufn;
 | 
			
		||||
    st->cbuf = (char *) string;
 | 
			
		||||
    st->cbuf = (unsigned char *) string;
 | 
			
		||||
    st->fp = NULL;
 | 
			
		||||
    ddsrt_xmlp_new_common (st);
 | 
			
		||||
    ddsrt_xmlp_new_setCB (st, varg, cb);
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +198,7 @@ static int make_chars_available (struct ddsrt_xmlp_state *st, size_t nmin)
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
        /* buffer is owned by caller if fp = NULL, and by us if fp != NULL */
 | 
			
		||||
        if (st->cbufp + st->cbufmax < nmin) {
 | 
			
		||||
        if (st->cbufmax < st->cbufp + nmin) {
 | 
			
		||||
            st->cbufmax = st->cbufp + nmin;
 | 
			
		||||
            st->cbuf = ddsrt_realloc (st->cbuf, st->cbufmax);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -239,7 +239,7 @@ static void rewind_to_input_marker (struct ddsrt_xmlp_state *st)
 | 
			
		|||
 | 
			
		||||
static int next_char (struct ddsrt_xmlp_state *st)
 | 
			
		||||
{
 | 
			
		||||
    char c;
 | 
			
		||||
    unsigned char c;
 | 
			
		||||
    if (!make_chars_available (st, 1)) {
 | 
			
		||||
        return TOK_EOF;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -459,10 +459,10 @@ static int next_token_tag_withoutclose (struct ddsrt_xmlp_state *st, char **payl
 | 
			
		|||
    } else {
 | 
			
		||||
        int tok = TOK_OPEN_TAG;
 | 
			
		||||
        /* pre: peek_char(st) == '<' */
 | 
			
		||||
        next_char (st);
 | 
			
		||||
        (void) next_char (st);
 | 
			
		||||
        if (peek_char (st) == '/') {
 | 
			
		||||
            tok = TOK_CLOSE_TAG;
 | 
			
		||||
            next_char (st);
 | 
			
		||||
            (void) next_char (st);
 | 
			
		||||
        }
 | 
			
		||||
        /* we only do tag names that are identifiers */
 | 
			
		||||
        if (peek_char (st) == '>' && (st->options & DDSRT_XMLP_ANONYMOUS_CLOSE_TAG)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -500,8 +500,8 @@ static int skip_comment (struct ddsrt_xmlp_state *st)
 | 
			
		|||
    if (!peek_chars (st, "<!--", 1)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    while ((peek_char (st) != TOK_EOF && peek_char (st) != '-') || !peek_chars (st, "-->", 0)) {
 | 
			
		||||
        next_char (st);
 | 
			
		||||
    while (peek_char (st) != TOK_EOF && (peek_char (st) != '-' || !peek_chars (st, "-->", 0))) {
 | 
			
		||||
        (void) next_char (st);
 | 
			
		||||
    }
 | 
			
		||||
    if (peek_chars (st, "-->", 1)) {
 | 
			
		||||
        return 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -514,7 +514,7 @@ static void processing_instruction (struct ddsrt_xmlp_state *st, const char *end
 | 
			
		|||
{
 | 
			
		||||
    /* just after <?; skip everything up to and include ?> */
 | 
			
		||||
    while (peek_char (st) != TOK_EOF && !peek_chars (st, end, 1)) {
 | 
			
		||||
        next_char (st);
 | 
			
		||||
        (void) next_char (st);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -551,7 +551,7 @@ static int next_token (struct ddsrt_xmlp_state *st, char **payload)
 | 
			
		|||
        st->prevline = st->line;
 | 
			
		||||
        do {
 | 
			
		||||
            while (qq_isspace (peek_char (st))) {
 | 
			
		||||
                next_char (st);
 | 
			
		||||
                (void) next_char (st);
 | 
			
		||||
            }
 | 
			
		||||
        } while ((cmt = skip_comment (st)) > 0);
 | 
			
		||||
        if (cmt == TOK_ERROR) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ list(APPEND sources
 | 
			
		|||
  "thread_cleanup.c"
 | 
			
		||||
  "string.c"
 | 
			
		||||
  "log.c"
 | 
			
		||||
  "hopscotch.c"
 | 
			
		||||
  "random.c"
 | 
			
		||||
  "retcode.c"
 | 
			
		||||
  "strlcpy.c"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										209
									
								
								src/ddsrt/tests/hopscotch.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								src/ddsrt/tests/hopscotch.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,209 @@
 | 
			
		|||
/*
 | 
			
		||||
* Copyright(c) 2019 ADLINK Technology Limited and others
 | 
			
		||||
*
 | 
			
		||||
* This program and the accompanying materials are made available under the
 | 
			
		||||
* terms of the Eclipse Public License v. 2.0 which is available at
 | 
			
		||||
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
 | 
			
		||||
* v. 1.0 which is available at
 | 
			
		||||
* http://www.eclipse.org/org/documents/edl-v10.php.
 | 
			
		||||
*
 | 
			
		||||
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 | 
			
		||||
*/
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include "CUnit/Test.h"
 | 
			
		||||
#include "CUnit/Theory.h"
 | 
			
		||||
 | 
			
		||||
#include "dds/ddsrt/random.h"
 | 
			
		||||
#include "dds/ddsrt/heap.h"
 | 
			
		||||
#include "dds/ddsrt/time.h"
 | 
			
		||||
#include "dds/ddsrt/hopscotch.h"
 | 
			
		||||
 | 
			
		||||
#define MAX_NKEYS 10000
 | 
			
		||||
#define MAX_ITERS 1000000
 | 
			
		||||
 | 
			
		||||
static int nkeys_hist[MAX_NKEYS+1];
 | 
			
		||||
static uint32_t objs[MAX_NKEYS], keys[MAX_NKEYS];
 | 
			
		||||
static uint32_t next_v;
 | 
			
		||||
static ddsrt_prng_t prng;
 | 
			
		||||
 | 
			
		||||
static uint32_t hash_uint32 (const void *v)
 | 
			
		||||
{
 | 
			
		||||
  const uint64_t m = UINT64_C (10242350189706880077);
 | 
			
		||||
  const uint32_t h = (uint32_t) ((*((uint32_t *) v) * m) >> 32);
 | 
			
		||||
  return h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int equals_uint32 (const void *a, const void *b)
 | 
			
		||||
{
 | 
			
		||||
  return *((uint32_t *) a) == *((uint32_t *) b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int compare_uint32 (const void *va, const void *vb)
 | 
			
		||||
{
 | 
			
		||||
  const uint32_t *a = va;
 | 
			
		||||
  const uint32_t *b = vb;
 | 
			
		||||
  return (*a == *b) ? 0 : (*a < *b) ? -1 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void swap (uint32_t *a, uint32_t *b)
 | 
			
		||||
{
 | 
			
		||||
  uint32_t t = *a;
 | 
			
		||||
  *a = *b;
 | 
			
		||||
  *b = t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void init (bool random)
 | 
			
		||||
{
 | 
			
		||||
  uint32_t i;
 | 
			
		||||
  ddsrt_prng_init_simple (&prng, ddsrt_random ());
 | 
			
		||||
  next_v = MAX_NKEYS;
 | 
			
		||||
  for (i = 0; i < MAX_NKEYS; i++)
 | 
			
		||||
  {
 | 
			
		||||
    nkeys_hist[i] = 0;
 | 
			
		||||
    keys[i] = i;
 | 
			
		||||
  }
 | 
			
		||||
  if (random)
 | 
			
		||||
  {
 | 
			
		||||
    /* Generate MAX_NKEYS unique random ints by repeatedly replacing
 | 
			
		||||
       duplicates with other random numbers (this'll take more time the
 | 
			
		||||
       larger MAX_NKEYS is, but for practical values, it is nearly
 | 
			
		||||
       instantaneous) */
 | 
			
		||||
    for (i = 0; i < MAX_NKEYS - 1; i++)
 | 
			
		||||
      objs[i] = ddsrt_prng_random (&prng);
 | 
			
		||||
    do {
 | 
			
		||||
      objs[i] = ddsrt_prng_random (&prng);
 | 
			
		||||
      qsort (objs, MAX_NKEYS, sizeof (*objs), compare_uint32);
 | 
			
		||||
      for (i = 1; i < MAX_NKEYS && objs[i-1] != objs[i]; i++)
 | 
			
		||||
        ;
 | 
			
		||||
    } while (i < MAX_NKEYS);
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    for (i = 0; i < MAX_NKEYS; i++)
 | 
			
		||||
      objs[i] = i;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ops {
 | 
			
		||||
  const char *name;
 | 
			
		||||
  void * (*new) (void);
 | 
			
		||||
  void (*free) (void *h);
 | 
			
		||||
  void * (*lookup) (void *h, const void *v);
 | 
			
		||||
  int (*add) (void *h, const void *v);
 | 
			
		||||
  int (*remove) (void *h, const void *v);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define WRAP(ret_, f_) static ret_ f_##_w (void *h, const void *v) { return f_ (h, v); }
 | 
			
		||||
WRAP(void *, ddsrt_hh_lookup);
 | 
			
		||||
WRAP(int, ddsrt_hh_add);
 | 
			
		||||
WRAP(int, ddsrt_hh_remove);
 | 
			
		||||
WRAP(void *, ddsrt_chh_lookup);
 | 
			
		||||
WRAP(int, ddsrt_chh_add);
 | 
			
		||||
WRAP(int, ddsrt_chh_remove);
 | 
			
		||||
WRAP(void *, ddsrt_ehh_lookup);
 | 
			
		||||
WRAP(int, ddsrt_ehh_add);
 | 
			
		||||
WRAP(int, ddsrt_ehh_remove);
 | 
			
		||||
#undef WRAP
 | 
			
		||||
 | 
			
		||||
static void free_buckets (void *bs, void *arg)
 | 
			
		||||
{
 | 
			
		||||
  /* nothing to worry about because this is single threaded */
 | 
			
		||||
  (void) arg;
 | 
			
		||||
  ddsrt_free (bs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *hhnew (void) { return ddsrt_hh_new (1, hash_uint32, equals_uint32); }
 | 
			
		||||
static void hhfree (void *h) { ddsrt_hh_free (h); }
 | 
			
		||||
static void *chhnew (void) { return ddsrt_chh_new (1, hash_uint32, equals_uint32, free_buckets, NULL); }
 | 
			
		||||
static void chhfree (void *h) { ddsrt_chh_free (h); }
 | 
			
		||||
static void *ehhnew (void) { return ddsrt_ehh_new (sizeof (uint32_t), 1, hash_uint32, equals_uint32); }
 | 
			
		||||
static void ehhfree (void *h) { ddsrt_ehh_free (h); }
 | 
			
		||||
 | 
			
		||||
static const struct ops hhops = {
 | 
			
		||||
  .name = "hh",
 | 
			
		||||
  .new = hhnew,
 | 
			
		||||
  .free = hhfree,
 | 
			
		||||
  .lookup = ddsrt_hh_lookup_w,
 | 
			
		||||
  .add = ddsrt_hh_add_w,
 | 
			
		||||
  .remove = ddsrt_hh_remove_w
 | 
			
		||||
};
 | 
			
		||||
static const struct ops chhops = {
 | 
			
		||||
  .name = "chh",
 | 
			
		||||
  .new = chhnew,
 | 
			
		||||
  .free = chhfree,
 | 
			
		||||
  .lookup = ddsrt_chh_lookup_w,
 | 
			
		||||
  .add = ddsrt_chh_add_w,
 | 
			
		||||
  .remove = ddsrt_chh_remove_w
 | 
			
		||||
};
 | 
			
		||||
static const struct ops ehhops = {
 | 
			
		||||
  .name = "ehh",
 | 
			
		||||
  .new = ehhnew,
 | 
			
		||||
  .free = ehhfree,
 | 
			
		||||
  .lookup = ddsrt_ehh_lookup_w,
 | 
			
		||||
  .add = ddsrt_ehh_add_w,
 | 
			
		||||
  .remove = ddsrt_ehh_remove_w
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void adj_nop (uint32_t *v) { (void) v; }
 | 
			
		||||
static void adj_seq (uint32_t *v) { *v = next_v++; }
 | 
			
		||||
 | 
			
		||||
typedef void (*adj_fun_t) (uint32_t *v);
 | 
			
		||||
 | 
			
		||||
CU_TheoryDataPoints (ddsrt_hopscotch, random) = {
 | 
			
		||||
  CU_DataPoints (const struct ops *, &hhops,  &chhops, &ehhops,  &hhops,  &chhops, &ehhops),
 | 
			
		||||
  CU_DataPoints (bool,               true,    true,    true,     false,   false,   false),
 | 
			
		||||
  CU_DataPoints (adj_fun_t,          adj_nop, adj_nop, adj_nop,  adj_seq, adj_seq, adj_seq),
 | 
			
		||||
  CU_DataPoints (const char *,       "nop",   "nop",   "nop",    "seq",   "seq",   "seq")
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
CU_Theory ((const struct ops *ops, bool random, adj_fun_t adj, const char *adjname), ddsrt_hopscotch, random)
 | 
			
		||||
{
 | 
			
		||||
  printf ("%s random=%d adj=%s", ops->name, random, adjname);
 | 
			
		||||
  fflush (stdout);
 | 
			
		||||
  init (random);
 | 
			
		||||
  void *h = ops->new ();
 | 
			
		||||
  uint32_t i, nk = 0;
 | 
			
		||||
  uint64_t nn = 0;
 | 
			
		||||
  dds_time_t t0, t1;
 | 
			
		||||
  t0 = ddsrt_time_monotonic ();
 | 
			
		||||
  for (uint32_t iter = 0; iter < MAX_ITERS; iter++)
 | 
			
		||||
  {
 | 
			
		||||
    int r;
 | 
			
		||||
    assert (nk <= MAX_NKEYS);
 | 
			
		||||
    nkeys_hist[nk]++;
 | 
			
		||||
    if (nk == MAX_NKEYS || (nk > 0 && (ddsrt_prng_random (&prng) & 1)))
 | 
			
		||||
    {
 | 
			
		||||
      i = ddsrt_prng_random (&prng) % nk;
 | 
			
		||||
      if (!ops->lookup (h, &objs[keys[i]]))
 | 
			
		||||
        CU_FAIL_FATAL ("key not present\n");
 | 
			
		||||
      r = ops->remove (h, &objs[keys[i]]);
 | 
			
		||||
      if (!r)
 | 
			
		||||
        CU_FAIL_FATAL ("remove failed\n");
 | 
			
		||||
      if (ops->lookup (h, &objs[keys[i]]))
 | 
			
		||||
        CU_FAIL_FATAL ("key still present\n");
 | 
			
		||||
      adj (&objs[keys[i]]);
 | 
			
		||||
      swap (&keys[i], &keys[nk-1]);
 | 
			
		||||
      nk--;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      i = nk + (ddsrt_prng_random (&prng) % (MAX_NKEYS - nk));
 | 
			
		||||
      if (ops->lookup (h, &objs[keys[i]]))
 | 
			
		||||
        CU_FAIL_FATAL ("key already present\n");
 | 
			
		||||
      r = ops->add (h, &objs[keys[i]]);
 | 
			
		||||
      if (!r)
 | 
			
		||||
        CU_FAIL_FATAL ("add failed\n");
 | 
			
		||||
      if (!ops->lookup (h, &objs[keys[i]]))
 | 
			
		||||
        CU_FAIL_FATAL ("key still not present\n");
 | 
			
		||||
      swap (&keys[i], &keys[nk]);
 | 
			
		||||
      nk++;
 | 
			
		||||
    }
 | 
			
		||||
    nn++;
 | 
			
		||||
  }
 | 
			
		||||
  t1 = ddsrt_time_monotonic ();
 | 
			
		||||
  ops->free (h);
 | 
			
		||||
  printf (" %"PRIu64" %.0f ns/cycle\n", nn, (double) (t1 - t0) / (double) nn);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -435,13 +435,13 @@ static void abort_handler (int sig)
 | 
			
		|||
static void abort_log (void *arg, const dds_log_data_t *info)
 | 
			
		||||
{
 | 
			
		||||
  (void) arg;
 | 
			
		||||
  ddsrt_strlcpy (abort_message, info->message, sizeof (abort_message));
 | 
			
		||||
  (void) ddsrt_strlcpy (abort_message, info->message, sizeof (abort_message));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void abort_trace (void *arg, const dds_log_data_t *info)
 | 
			
		||||
{
 | 
			
		||||
  (void) arg;
 | 
			
		||||
  ddsrt_strlcpy (abort_message_trace, info->message, sizeof (abort_message_trace));
 | 
			
		||||
  (void) ddsrt_strlcpy (abort_message_trace, info->message, sizeof (abort_message_trace));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CU_TheoryDataPoints(dds_log, fatal_aborts) = {
 | 
			
		||||
| 
						 | 
				
			
			@ -462,6 +462,7 @@ CU_Theory((bool local, int mode, bool expect_in_trace), dds_log, fatal_aborts)
 | 
			
		|||
#if TEST_DDS_LC_FATAL
 | 
			
		||||
  struct sigaction action, oldaction;
 | 
			
		||||
  action.sa_flags = 0;
 | 
			
		||||
  sigemptyset (&action.sa_mask);
 | 
			
		||||
  action.sa_handler = abort_handler;
 | 
			
		||||
 | 
			
		||||
  if (sigsetjmp (abort_jmpbuf, 0) != 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -157,7 +157,7 @@ CU_Test(ddsrt_sockets, gethostname)
 | 
			
		|||
 | 
			
		||||
  sysbuf[0] = '\0';
 | 
			
		||||
#if LWIP_SOCKET
 | 
			
		||||
  ddsrt_strlcpy(sysbuf, "localhost", sizeof(sysbuf));
 | 
			
		||||
  (void) ddsrt_strlcpy(sysbuf, "localhost", sizeof(sysbuf));
 | 
			
		||||
#else
 | 
			
		||||
  int ret = gethostname(sysbuf, sizeof(sysbuf));
 | 
			
		||||
  CU_ASSERT_EQUAL(ret, 0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue