//assoc_insert函数会调用本函数,当item数量到了哈希表表长的1.5被才会调用 
static void assoc_start_expand(void) {
    if (started_expanding)
        return;
    started_expanding = true;
    pthread_cond_signal(&maintenance_cond);
}
Example #2
0
/**
 * Search worker. This method was invoked on threads launched from `main`.
 */
void *search_worker(void *arg)
{
    enum file_type t;
    worker_params *params = (worker_params *)arg;
    file_queue_node *current;
    const size_t out_len = 1024;
    int utf8_pattern_len = strlen(op.pattern);

    while (1) {
        // This worker takes out a search target file from the queue. If the queue is empty, worker
        // will be waiting until find at least one target file.
        pthread_mutex_lock(&file_mutex);
        while ((current = peek_file_for_search(params->queue)) == NULL) {
            // Break this loop if all files was searched.
            if (is_complete_scan_file()) {
                pthread_mutex_unlock(&file_mutex);
                return NULL;
            }
            pthread_cond_wait(&file_cond, &file_mutex);
        }
        pthread_mutex_unlock(&file_mutex);

        // Check file type of the target file, then if it is a binary, we skip it because the hw is
        // the software in order to search "source code", so searching binary files is not good.
        int fd = open(current->filename, O_RDONLY);
        if (fd != -1 && (t = detect_file_type(fd, current->filename)) != FILE_TYPE_BINARY) {
            char *pattern = op.pattern;

            // Convert the pattern to appropriate encoding if an encoding of the target file is
            // not UTF-8.
            char out[out_len + 1], pattern_len = utf8_pattern_len;
            if (t == FILE_TYPE_EUC_JP || t == FILE_TYPE_SHIFT_JIS) {
                if (t == FILE_TYPE_EUC_JP) {
                    to_euc(op.pattern, utf8_pattern_len, out, out_len);
                } else if (t == FILE_TYPE_SHIFT_JIS) {
                    to_sjis(op.pattern, utf8_pattern_len, out, out_len);
                }
                pattern = out;
                pattern_len = strlen(pattern);
            }

            // Searching.
            match_line_list *match_lines = create_match_line_list();
            int match_count = search(fd, pattern, pattern_len, t, match_lines, params->index);

            if (match_count > 0) {
                // Set additional data to the queue data because it will be used on print worker in
                // order to print results to the console. `match_lines` variable will be released
                // along with the file queue when it is released.
                current->matched      = true;
                current->match_lines  = match_lines;
                current->t            = t;
            } else {
                // If the pattern was not matched, the lines queue is no longer needed, so do free.
                free_match_line_list(match_lines);
            }
        }

        // Wake up print worker.
        current->searched = true;
        pthread_cond_signal(&print_cond);

        close(fd);
    }

    return NULL;
}
Example #3
0
static void worker_thread(void *arg)
{
    uintptr_t no = (uintptr_t) arg;
    unsigned int i;
    lkey_t key;
    val_t getval;

    /*
     * increment begin_thread_num, and wait for broadcast signal from last created thread
     */
    if (system_variables.thread_num != 1) {
      pthread_mutex_lock(&begin_mtx);
      begin_thread_num++;
      if (begin_thread_num == system_variables.thread_num)
	pthread_cond_broadcast(&begin_cond);
      else {
	while (begin_thread_num < system_variables.thread_num)
	  pthread_cond_wait(&begin_cond, &begin_mtx);	
      }
      pthread_mutex_unlock(&begin_mtx);
    }

    gettimeofday(&stat_data[no].begin, NULL);
    sum[no] = 0;

    /*  main loop */
    key = no * system_variables.item_num;
    for (i = 0; i < system_variables.item_num; i++) {
      ++key;
      if (0 < system_variables.verbose)
	fprintf(stderr, "thread[%lu] add: %lu\n", (uintptr_t)no,
		(uintptr_t) key);

      if (add(list, (lkey_t) key, (val_t)key) != true)
	fprintf (stderr, "ERROR[%lu]: add %lu\n", (uintptr_t)no, (uintptr_t)key);

      if (1 < system_variables.verbose)
	show_list(list);
      
      //      usleep(no);
      //      pthread_yield(NULL);
    }

    usleep(no * 10);

    key = no * system_variables.item_num;
    for (i = 0; i < system_variables.item_num; i++) {
      ++key;
      if (delete(list, (lkey_t) key, &getval) != true) {
	printf ("ERROR[%lu]: del %lu\n", (uintptr_t)no, (uintptr_t)key);
      }

      if (1 < system_variables.verbose)
	show_list(list);
      
      if (0 < system_variables.verbose)
	fprintf(stderr, "delete: val = %ld\n", (lkey_t) getval);
      
      sum[no] += getval;
      
      check[getval]++;
    }

    /* send signal */
    gettimeofday(&stat_data[no].end, NULL);
    pthread_mutex_lock(&end_mtx);
    end_thread_num++;
    pthread_cond_signal(&end_cond);
    pthread_mutex_unlock(&end_mtx);
}
Example #4
0
int
main(int argc, char **argv)
{
  int i;
  sigset_t set;
#if ENABLE_MPEGTS
  uint32_t adapter_mask = 0;
#endif
  int  log_level   = LOG_INFO;
  int  log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG;
  const char *log_debug = NULL, *log_trace = NULL;
  gid_t gid = -1;
  uid_t uid = -1;
  char buf[512];
  FILE *pidfile = NULL;
  extern int dvb_bouquets_parse;

  main_tid = pthread_self();

  /* Setup global mutexes */
  pthread_mutex_init(&fork_lock, NULL);
  pthread_mutex_init(&global_lock, NULL);
  pthread_mutex_init(&tasklet_lock, NULL);
  pthread_mutex_init(&atomic_lock, NULL);
  pthread_cond_init(&gtimer_cond, NULL);
  pthread_cond_init(&tasklet_cond, NULL);
  TAILQ_INIT(&tasklets);

  /* Defaults */
  tvheadend_webui_port      = 9981;
  tvheadend_webroot         = NULL;
  tvheadend_htsp_port       = 9982;
  tvheadend_htsp_port_extra = 0;
  time(&dispatch_clock);

  /* Command line options */
  int         opt_help         = 0,
              opt_version      = 0,
              opt_fork         = 0,
              opt_firstrun     = 0,
              opt_stderr       = 0,
              opt_syslog       = 0,
              opt_nosyslog     = 0,
              opt_uidebug      = 0,
              opt_abort        = 0,
              opt_noacl        = 0,
              opt_fileline     = 0,
              opt_threadid     = 0,
              opt_libav        = 0,
              opt_ipv6         = 0,
              opt_satip_rtsp   = 0,
#if ENABLE_TSFILE
              opt_tsfile_tuner = 0,
#endif
              opt_dump         = 0,
              opt_xspf         = 0,
              opt_dbus         = 0,
              opt_dbus_session = 0,
              opt_nobackup     = 0,
              opt_nobat        = 0;
  const char *opt_config       = NULL,
             *opt_user         = NULL,
             *opt_group        = NULL,
             *opt_logpath      = NULL,
             *opt_log_debug    = NULL,
             *opt_log_trace    = NULL,
             *opt_pidpath      = "/var/run/tvheadend.pid",
#if ENABLE_LINUXDVB
             *opt_dvb_adapters = NULL,
#endif
             *opt_bindaddr     = NULL,
             *opt_subscribe    = NULL,
             *opt_user_agent   = NULL;
  str_list_t  opt_satip_xml    = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  str_list_t  opt_tsfile       = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) };
  cmdline_opt_t cmdline_opts[] = {
    {   0, NULL,        N_("Generic Options"),         OPT_BOOL, NULL         },
    { 'h', "help",      N_("Show this page"),          OPT_BOOL, &opt_help    },
    { 'v', "version",   N_("Show version information"),OPT_BOOL, &opt_version },

    {   0, NULL,        N_("Service Configuration"),   OPT_BOOL, NULL         },
    { 'c', "config",    N_("Alternate config path"),   OPT_STR,  &opt_config  },
    { 'B', "nobackup",  N_("Don't backup config tree at upgrade"), OPT_BOOL, &opt_nobackup },
    { 'f', "fork",      N_("Fork and run as daemon"),  OPT_BOOL, &opt_fork    },
    { 'u', "user",      N_("Run as user"),             OPT_STR,  &opt_user    },
    { 'g', "group",     N_("Run as group"),            OPT_STR,  &opt_group   },
    { 'p', "pid",       N_("Alternate pid path"),      OPT_STR,  &opt_pidpath },
    { 'C', "firstrun",  N_("If no user account exists then create one with\n"
	                   "no username and no password. Use with care as\n"
	                   "it will allow world-wide administrative access\n"
	                   "to your Tvheadend installation until you edit/create\n"
	                   "access-control from within the Tvheadend UI"),
      OPT_BOOL, &opt_firstrun },
#if ENABLE_DBUS_1
    { 'U', "dbus",      N_("Enable DBus"),
      OPT_BOOL, &opt_dbus },
    { 'e', "dbus_session", N_("DBus - use the session message bus instead system one"),
      OPT_BOOL, &opt_dbus_session },
#endif
#if ENABLE_LINUXDVB
    { 'a', "adapters",  N_("Only use specified DVB adapters (comma separated)"),
      OPT_STR, &opt_dvb_adapters },
#endif
#if ENABLE_SATIP_SERVER
    {   0, "satip_rtsp", N_("SAT>IP RTSP port number for server\n"
                            "(default: -1 = disable, 0 = webconfig, standard port is 554)"),
      OPT_INT, &opt_satip_rtsp },
#endif
#if ENABLE_SATIP_CLIENT
    {   0, "satip_xml", N_("URL with the SAT>IP server XML location"),
      OPT_STR_LIST, &opt_satip_xml },
#endif
    {   0, NULL,         N_("Server Connectivity"),    OPT_BOOL, NULL         },
    { '6', "ipv6",       N_("Listen on IPv6"),         OPT_BOOL, &opt_ipv6    },
    { 'b', "bindaddr",   N_("Specify bind address"),   OPT_STR,  &opt_bindaddr},
    {   0, "http_port",  N_("Specify alternative http port"),
      OPT_INT, &tvheadend_webui_port },
    {   0, "http_root",  N_("Specify alternative http webroot"),
      OPT_STR, &tvheadend_webroot },
    {   0, "htsp_port",  N_("Specify alternative htsp port"),
      OPT_INT, &tvheadend_htsp_port },
    {   0, "htsp_port2", N_("Specify extra htsp port"),
      OPT_INT, &tvheadend_htsp_port_extra },
    {   0, "useragent",  N_("Specify User-Agent header for the http client"),
      OPT_STR, &opt_user_agent },
    {   0, "xspf",       N_("Use XSPF playlist instead of M3U"),
      OPT_BOOL, &opt_xspf },

    {   0, NULL,        N_("Debug Options"),           OPT_BOOL, NULL         },
    { 'd', "stderr",    N_("Enable debug on stderr"),  OPT_BOOL, &opt_stderr  },
    { 's', "syslog",    N_("Enable debug to syslog"),  OPT_BOOL, &opt_syslog  },
    { 'S', "nosyslog",  N_("Disable syslog (all msgs)"), OPT_BOOL, &opt_nosyslog },
    { 'l', "logfile",   N_("Enable debug to file"),    OPT_STR,  &opt_logpath },
    {   0, "debug",     N_("Enable debug subsystems"),  OPT_STR,  &opt_log_debug },
#if ENABLE_TRACE
    {   0, "trace",     N_("Enable trace subsystems"), OPT_STR,  &opt_log_trace },
#endif
    {   0, "fileline",  N_("Add file and line numbers to debug"), OPT_BOOL, &opt_fileline },
    {   0, "threadid",  N_("Add the thread ID to debug"), OPT_BOOL, &opt_threadid },
#if ENABLE_LIBAV
    {   0, "libav",     N_("More verbose libav log"),  OPT_BOOL, &opt_libav },
#endif
    {   0, "uidebug",   N_("Enable webUI debug (non-minified JS)"), OPT_BOOL, &opt_uidebug },
    { 'A', "abort",     N_("Immediately abort"),       OPT_BOOL, &opt_abort   },
    { 'D', "dump",      N_("Enable coredumps for daemon"), OPT_BOOL, &opt_dump },
    {   0, "noacl",     N_("Disable all access control checks"),
      OPT_BOOL, &opt_noacl },
    {   0, "nobat",     N_("Disable DVB bouquets"),
      OPT_BOOL, &opt_nobat },
    { 'j', "join",      N_("Subscribe to a service permanently"),
      OPT_STR, &opt_subscribe },


#if ENABLE_TSFILE || ENABLE_TSDEBUG
    { 0, NULL, N_("Testing options"), OPT_BOOL, NULL },
    { 0, "tsfile_tuners", N_("Number of tsfile tuners"), OPT_INT, &opt_tsfile_tuner },
    { 0, "tsfile", N_("tsfile input (mux file)"), OPT_STR_LIST, &opt_tsfile },
#endif
#if ENABLE_TSDEBUG
    { 0, "tsdebug", N_("Output directory for tsdebug"), OPT_STR, &tvheadend_tsdebug },
#endif

  };

  /* Get current directory */
  tvheadend_cwd0 = dirname(tvh_strdupa(argv[0]));
  tvheadend_cwd = dirname(tvh_strdupa(tvheadend_cwd0));

  /* Set locale */
  setlocale(LC_ALL, "");
  setlocale(LC_NUMERIC, "C");
  tvh_gettext_init();

  /* make sure the timezone is set */
  tzset();

  /* Process command line */
  for (i = 1; i < argc; i++) {

    /* Find option */
    cmdline_opt_t *opt
      = cmdline_opt_find(cmdline_opts, ARRAY_SIZE(cmdline_opts), argv[i]);
    if (!opt)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 _("invalid option specified [%s]"), argv[i]);

    /* Process */
    if (opt->type == OPT_BOOL)
      *((int*)opt->param) = 1;
    else if (++i == argc)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts),
                 _("option %s requires a value"), opt->lopt);
    else if (opt->type == OPT_INT)
      *((int*)opt->param) = atoi(argv[i]);
    else if (opt->type == OPT_STR_LIST) {
      str_list_t *strl = opt->param;
      if (strl->num < strl->max)
        strl->str[strl->num++] = argv[i];
    }
    else
      *((char**)opt->param) = argv[i];

    /* Stop processing */
    if (opt_help)
      show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), NULL);
    if (opt_version)
      show_version(argv[0]);
  }

  /* Additional cmdline processing */
  if (opt_nobat)
    dvb_bouquets_parse = 0;
#if ENABLE_LINUXDVB
  if (!opt_dvb_adapters) {
    adapter_mask = ~0;
  } else {
    char *p, *e;
    char *r = NULL;
    char *dvb_adapters = strdup(opt_dvb_adapters);
    adapter_mask = 0x0;
    p = strtok_r(dvb_adapters, ",", &r);
    while (p) {
      int a = strtol(p, &e, 10);
      if (*e != 0 || a < 0 || a > 31) {
        fprintf(stderr, _("Invalid adapter number '%s'\n"), p);
        free(dvb_adapters);
        return 1;
      }
      adapter_mask |= (1 << a);
      p = strtok_r(NULL, ",", &r);
    }
    free(dvb_adapters);
    if (!adapter_mask) {
      fprintf(stderr, "%s", _("No adapters specified!\n"));
      return 1;
    }
  }
#endif
  if (tvheadend_webroot) {
    char *tmp;
    if (*tvheadend_webroot == '/')
      tmp = strdup(tvheadend_webroot);
    else {
      tmp = malloc(strlen(tvheadend_webroot)+2);
      *tmp = '/';
      strcpy(tmp+1, tvheadend_webroot);
    }
    if (tmp[strlen(tmp)-1] == '/')
      tmp[strlen(tmp)-1] = '\0';
    tvheadend_webroot = tmp;
  }
  tvheadend_webui_debug = opt_uidebug;

  /* Setup logging */
  if (isatty(2))
    log_options |= TVHLOG_OPT_DECORATE;
  if (opt_stderr || opt_syslog || opt_logpath) {
    if (!opt_log_trace && !opt_log_debug)
      log_debug      = "all";
    log_level      = LOG_DEBUG;
    if (opt_stderr)
      log_options   |= TVHLOG_OPT_DBG_STDERR;
    if (opt_syslog)
      log_options   |= TVHLOG_OPT_DBG_SYSLOG;
    if (opt_logpath)
      log_options   |= TVHLOG_OPT_DBG_FILE;
  }
  if (opt_nosyslog)
    log_options &= ~(TVHLOG_OPT_SYSLOG|TVHLOG_OPT_DBG_SYSLOG);
  if (opt_fileline)
    log_options |= TVHLOG_OPT_FILELINE;
  if (opt_threadid)
    log_options |= TVHLOG_OPT_THREAD;
  if (opt_libav)
    log_options |= TVHLOG_OPT_LIBAV;
  if (opt_log_trace) {
    log_level  = LOG_TRACE;
    log_trace  = opt_log_trace;
  }
  if (opt_log_debug)
    log_debug  = opt_log_debug;
    
  tvhlog_init(log_level, log_options, opt_logpath);
  tvhlog_set_debug(log_debug);
  tvhlog_set_trace(log_trace);
  tvhinfo("main", "Log started");
 
  signal(SIGPIPE, handle_sigpipe); // will be redundant later
  signal(SIGILL, handle_sigill);   // see handler..

  /* Set priviledges */
  if(opt_fork || opt_group || opt_user) {
    const char *homedir;
    struct group  *grp = getgrnam(opt_group ?: "video");
    struct passwd *pw  = opt_user ? getpwnam(opt_user) : NULL;

    if(grp != NULL) {
      gid = grp->gr_gid;
    } else {
      gid = 1;
    }

    if (pw != NULL) {
      if (getuid() != pw->pw_uid) {
        gid_t glist[16];
        int gnum;
        gnum = get_user_groups(pw, glist, ARRAY_SIZE(glist));
        if (gnum > 0 && setgroups(gnum, glist)) {
          char buf[256] = "";
          int i;
          for (i = 0; i < gnum; i++)
            snprintf(buf + strlen(buf), sizeof(buf) - 1 - strlen(buf),
                     ",%d", glist[i]);
          tvhlog(LOG_ALERT, "START",
                 "setgroups(%s) failed, do you have permission?", buf+1);
          return 1;
        }
      }
      uid     = pw->pw_uid;
      homedir = pw->pw_dir;
      setenv("HOME", homedir, 1);
    } else {
      uid = 1;
    }
  }

  uuid_init();
  config_boot(opt_config, gid, uid);
  tcp_server_preinit(opt_ipv6);
  http_server_init(opt_bindaddr);    // bind to ports only
  htsp_init(opt_bindaddr);	     // bind to ports only
  satip_server_init(opt_satip_rtsp); // bind to ports only

  if (opt_fork)
    pidfile = tvh_fopen(opt_pidpath, "w+");

  if (gid != -1 && (getgid() != gid) && setgid(gid)) {
    tvhlog(LOG_ALERT, "START",
           "setgid(%d) failed, do you have permission?", gid);
    return 1;
  }
  if (uid != -1 && (getuid() != uid) && setuid(uid)) {
    tvhlog(LOG_ALERT, "START",
           "setuid(%d) failed, do you have permission?", uid);
    return 1;
  }

  /* Daemonise */
  if(opt_fork) {
    if(daemon(0, 0)) {
      exit(2);
    }
    if(pidfile != NULL) {
      fprintf(pidfile, "%d\n", getpid());
      fclose(pidfile);
    }

    /* Make dumpable */
    if (opt_dump) {
#ifdef PLATFORM_LINUX
      if (chdir("/tmp"))
        tvhwarn("START", "failed to change cwd to /tmp");
      prctl(PR_SET_DUMPABLE, 1);
#else
      tvhwarn("START", "Coredumps not implemented on your platform");
#endif
    }

    umask(0);
  }

  tvheadend_running = 1;

  /* Start log thread (must be done post fork) */
  tvhlog_start();

  /* Alter logging */
  if (opt_fork)
    tvhlog_options &= ~TVHLOG_OPT_STDERR;
  if (!isatty(2))
    tvhlog_options &= ~TVHLOG_OPT_DECORATE;
  
  /* Initialise clock */
  pthread_mutex_lock(&global_lock);
  time(&dispatch_clock);

  /* Signal handling */
  sigfillset(&set);
  sigprocmask(SIG_BLOCK, &set, NULL);
  trap_init(argv[0]);

  /* SSL library init */
  OPENSSL_config(NULL);
  SSL_load_error_strings();
  SSL_library_init();

  /* Initialise configuration */
  notify_init();
  idnode_init();
  spawn_init();
  config_init(opt_nobackup == 0);

  /**
   * Initialize subsystems
   */

  epg_in_load = 1;

  tvhthread_create(&tasklet_tid, NULL, tasklet_thread, NULL);

  dbus_server_init(opt_dbus, opt_dbus_session);

  intlconv_init();
  
  api_init();

  fsmonitor_init();

  libav_init();

  tvhtime_init();

  profile_init();

  imagecache_init();

  http_client_init(opt_user_agent);
  esfilter_init();

  bouquet_init();

  service_init();

  dvb_init();

#if ENABLE_MPEGTS
  mpegts_init(adapter_mask, &opt_satip_xml, &opt_tsfile, opt_tsfile_tuner);
#endif

  channel_init();

  bouquet_service_resolve();

  subscription_init();

  dvr_config_init();

  access_init(opt_firstrun, opt_noacl);

#if ENABLE_TIMESHIFT
  timeshift_init();
#endif

  tcp_server_init();
  webui_init(opt_xspf);
#if ENABLE_UPNP
  upnp_server_init(opt_bindaddr);
#endif

  service_mapper_init();

  descrambler_init();

  epggrab_init();
  epg_init();

  dvr_init();

  dbus_server_start();

  http_server_register();
  satip_server_register();
  htsp_register();

  if(opt_subscribe != NULL)
    subscription_dummy_join(opt_subscribe, 1);

  avahi_init();
  bonjour_init();

  epg_updated(); // cleanup now all prev ref's should have been created
  epg_in_load = 0;

  pthread_mutex_unlock(&global_lock);

  /**
   * Wait for SIGTERM / SIGINT, but only in this thread
   */

  sigemptyset(&set);
  sigaddset(&set, SIGTERM);
  sigaddset(&set, SIGINT);

  signal(SIGTERM, doexit);
  signal(SIGINT, doexit);

  pthread_sigmask(SIG_UNBLOCK, &set, NULL);

  tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, "
         "running as PID:%d UID:%d GID:%d, CWD:%s CNF:%s",
         tvheadend_version,
         getpid(), getuid(), getgid(), getcwd(buf, sizeof(buf)),
         hts_settings_get_root());

  if(opt_abort)
    abort();

  mainloop();

#if ENABLE_DBUS_1
  tvhftrace("main", dbus_server_done);
#endif
#if ENABLE_UPNP
  tvhftrace("main", upnp_server_done);
#endif
  tvhftrace("main", satip_server_done);
  tvhftrace("main", htsp_done);
  tvhftrace("main", http_server_done);
  tvhftrace("main", webui_done);
  tvhftrace("main", fsmonitor_done);
  tvhftrace("main", http_client_done);
  tvhftrace("main", tcp_server_done);

  // Note: the locking is obviously a bit redundant, but without
  //       we need to disable the gtimer_arm call in epg_save()
  pthread_mutex_lock(&global_lock);
  tvhftrace("main", epg_save);

#if ENABLE_TIMESHIFT
  tvhftrace("main", timeshift_term);
#endif
  pthread_mutex_unlock(&global_lock);

  tvhftrace("main", epggrab_done);
#if ENABLE_MPEGTS
  tvhftrace("main", mpegts_done);
#endif
  tvhftrace("main", descrambler_done);
  tvhftrace("main", service_mapper_done);
  tvhftrace("main", service_done);
  tvhftrace("main", channel_done);
  tvhftrace("main", bouquet_done);
  tvhftrace("main", dvr_done);
  tvhftrace("main", subscription_done);
  tvhftrace("main", access_done);
  tvhftrace("main", epg_done);
  tvhftrace("main", avahi_done);
  tvhftrace("main", bonjour_done);
  tvhftrace("main", imagecache_done);
  tvhftrace("main", lang_code_done);
  tvhftrace("main", api_done);

  tvhtrace("main", "tasklet enter");
  pthread_cond_signal(&tasklet_cond);
  pthread_join(tasklet_tid, NULL);
  tvhtrace("main", "tasklet thread end");
  tasklet_flush();
  tvhtrace("main", "tasklet leave");

  tvhftrace("main", hts_settings_done);
  tvhftrace("main", dvb_done);
  tvhftrace("main", lang_str_done);
  tvhftrace("main", esfilter_done);
  tvhftrace("main", profile_done);
  tvhftrace("main", intlconv_done);
  tvhftrace("main", urlparse_done);
  tvhftrace("main", idnode_done);
  tvhftrace("main", notify_done);
  tvhftrace("main", spawn_done);

  tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend");
  tvhlog_end();

  tvhftrace("main", config_done);

  if(opt_fork)
    unlink(opt_pidpath);
    
#if ENABLE_TSFILE
  free(opt_tsfile.str);
#endif
  free(opt_satip_xml.str);

  /* OpenSSL - welcome to the "cleanup" hell */
  ENGINE_cleanup();
  RAND_cleanup();
  CRYPTO_cleanup_all_ex_data();
  EVP_cleanup();
  CONF_modules_free();
#ifndef OPENSSL_NO_COMP
  COMP_zlib_cleanup();
#endif
  ERR_remove_state(0);
  ERR_free_strings();
#ifndef OPENSSL_NO_COMP
  sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
#endif
  /* end of OpenSSL cleanup code */

#if ENABLE_DBUS_1
  extern void dbus_shutdown(void);
  if (opt_dbus) dbus_shutdown();
#endif
  tvh_gettext_done();
  return 0;
}

/**
 *
 */
void
tvh_str_set(char **strp, const char *src)
{
  free(*strp);
  *strp = src ? strdup(src) : NULL;
}


/**
 *
 */
int
tvh_str_update(char **strp, const char *src)
{
  if(src == NULL)
    return 0;
  free(*strp);
  *strp = strdup(src);
  return 1;
}


/**
 *
 */
void
scopedunlock(pthread_mutex_t **mtxp)
{
  pthread_mutex_unlock(*mtxp);
}
int OS_COND_SIGNAL(OS_COND* cond)
{
    return (pthread_cond_signal(cond));
}
Example #6
0
void *commands_thread(void *arg)
{
  const Position *position = ((Commands_thread_arg*) arg)->position;
  Move **first_move = ((Commands_thread_arg*) arg)->first_move;
  pthread_cond_t *command_cond =  ((Commands_thread_arg*) arg)->command_cond;
  pthread_cond_t *position_cond =  ((Commands_thread_arg*) arg)->position_cond;
  pthread_cond_t *network_cond =  ((Commands_thread_arg*) arg)->network_cond;
  Serial_connection *robot = ((Commands_thread_arg*) arg)->robot;
  Commands_infos *commands_infos = ((Commands_thread_arg*) arg)->commands_infos;

  LOG_DEBUG("Commands thread started\n");

  pthread_mutex_lock(&robot->free);
  //mutex_and_send(robot, "rpid s\r", "write rpid s unsucessful\n");

  for(;;)
  {
    // Wait until we get a set of commands
    while(*first_move == NULL)
      wait_time_cond(command_cond, robot, COMMAND_CHECK_INTERVAL);
    LOG_DEBUG("Command : New set of commands\n");

    Move *current_first_move = *first_move;
    Move current_move = *current_first_move;
    LOG_DEBUG("Command : New move : %d, %d, %d : %d\n",
      (int) current_move.goal.x, (int) current_move.goal.y, (int) current_move.goal.t, current_move.speed);

    int goal_reached = 0;
    int orientation_phase = -1;
    int move_phase = -1;
    int bypass_phase = -1;
    int left = 0, right = 0, return_towards_obs = 0, is_beginning_defined = 0;
    int return_to_direction = -1;
    int count_dbg = 0;
    Position begin_bypass_position;
    char command[500];

    for(;;)
    {
      // Check if we are on desired position
      /*if ((*first_move)->type == POSITION && check_desired_pos(position, &(current_move.goal)))
      {
        //stop();
        pthread_cond_signal(position_cond);
        LOG_DEBUG("Move ended\n");
        count_dbg = 0;
        goal_reached = 1;
      }*/

      // Check if we have another move to do
      if (goal_reached && (current_move.next_move != NULL))
      {
        current_move = *current_move.next_move;
        goal_reached = 0;
        orientation_phase = -1;
        move_phase = -1;
        bypass_phase = -1;
        left = right = return_towards_obs = is_beginning_defined = 0;
        return_to_direction = -1;
        LOG_DEBUG("Command : New move : %d, %d, %d : %d\n",
          (int) current_move.goal.x, (int) current_move.goal.y, (int) current_move.goal.t, current_move.speed);
      }
      else if (return_to_direction == 1)
      {
        if (position->t > (current_move.goal.t - 4)
              && position->t < (current_move.goal.t + 4))
        {
          sprintf(command, "stop\r");
          mutex_and_send(robot, command, "write stop unsuccessful");
          orientation_phase = 0;
        }

      }
      else if (return_to_direction == 0)
      {
        if(current_move.speed == 0)
        {
          sprintf(command, "pwm 1:0 2:0\r");
        }
        else
        {
          if(current_move.speed > 0)
            sprintf(command, "mogo 1:%d 2:%d\r", (current_move.speed*24/100)+10, (current_move.speed*24/100)+10);
          else
            sprintf(command, "mogo 1:%d 2:%d\r", -((current_move.speed*24/100)+10), -((current_move.speed*24/100)+10));
        }
        mutex_and_send(robot, command, "write mogo unsuccesful\n");
      }
      else if (!goal_reached)
      {
        if(current_move.speed == 0)
        {
          LOG_DEBUG("speed 0\n");
          mutex_and_send(robot, "stop\r", "write stop unsuccessful\n");
          goal_reached = 1;
          continue;
        }
        

	    	if (current_move.type == DIRECTION && bypass_phase == -1)
		    {
		    	//left wheel : 1; right wheel : 2
          if (abs(current_move.goal.t - position->t) < 4)
          {
            orientation_phase = 0;
          }

          if (orientation_phase == -1)
          {

            orientation_phase = 1;
            int a = (int)(current_move.goal.t - position->t + 360)%360;
            if(a > 180)
            {
  		    	  sprintf(command, "mogo 1:7 :-7\r");
              LOG_DEBUG("bleh1\n");
            }
            else
            {
              sprintf(command, "mogo 1:-7 2:7\r");
              LOG_DEBUG("bleh2\n");
            }
            mutex_and_send(robot,command,
                           "write mogo orientation unsuccesful\n");

          }
          else if (orientation_phase == 1)
          {
            if (position->t > (current_move.goal.t - 4)
                  && position->t < (current_move.goal.t + 4))
            {
              sprintf(command, "stop\r");
              mutex_and_send(robot, command, "write stop unsuccessful");
              orientation_phase = 0;
            }

          }
          else if (orientation_phase == 0)
          {
            if(current_move.speed == 0)
            {
              sprintf(command, "pwm 1:0 2:0\r");
            }
            else
            {
              if(current_move.speed > 0)
                sprintf(command, "mogo 1:%d 2:%d\r", (current_move.speed*24/100)+10, (current_move.speed*24/100)+10);
              else
                sprintf(command, "mogo 1:%d 2:%d\r", -((current_move.speed*24/100)+10), -((current_move.speed*24/100)+10));
            }
            mutex_and_send(robot, command, "write mogo unsuccesful\n");
          }
        }
        else if (current_move.type == POSITION && bypass_phase == -1)
        {
          if(current_move.goal.t == 0
                                  || abs(current_move.goal.t - position->t) < 4)
            orientation_phase = 0;

          if (orientation_phase == -1)
          {
            signal_begin_dep(commands_infos, network_cond);
            
            orientation_phase = 1;
		    	  //distance perimeter in which wheels have to move
		    	  //int dis = (position->t - current_move.theta)*WHEEL_SPACE*M_PI/360;
            int a = (int)(current_move.goal.t - position->t + 360)%360;
            if (a > 180)
            {
		    	    sprintf(command, "mogo 1:7 2:-7\r");
              LOG_DEBUG("bleh3\n");
            }
            else
            {
              sprintf(command, "mogo 1:-7 2:7\r");
              LOG_DEBUG("bleh4\n");
            }

            mutex_and_send(robot, command, "write mogo unsuccesful\n");

          }
          else if (orientation_phase == 1)
          {
            if (position->t > (current_move.goal.t - 4)
                  && position->t < (current_move.goal.t + 4))
              orientation_phase = 0;
          }
          else if (!orientation_phase)
          {
            if(move_phase == -1)
            {
              move_phase = 1;
              if(current_move.speed > 0)
              {
                sprintf(command, "mogo 1:%d 2:%d\r",
                          (current_move.speed*24/100)+10,
                          (current_move.speed*24/100)+10);
              }
              else
              {
                sprintf(command, "mogo 1:%d 2:%d\r",
                          -((current_move.speed*24/100)+10),
                          -((current_move.speed*24/100)+10));
              }
              mutex_and_send(robot, command, "write mogo unsuccesful\n");

            }
            else if (move_phase == 1)
            {
              if(position->x > current_move.goal.x - 5
                  && position->x < current_move.goal.x + 5
                  && position->y > current_move.goal.y - 5
                  && position->y < current_move.goal.y + 5)
              {
                sprintf(command, "stop\r");
                mutex_and_send(robot, command, "write stop unsuccesful\n");
                goal_reached = 1;
                move_phase = 0;
                signal_end_dep(commands_infos, network_cond);
              }

            }
          }
        }
        int distances[3];

        if (return_towards_obs == 1)
        {
          mutex_and_send(robot, "mogo 1:7 2:7\r",
                                            "write mogo unsuccessful\n");
          return_towards_obs = 0;
        }

        //sensor 0 1 2, right, left, middle
        sprintf(command, "sensor 0 1 2\r");
        send_command_get_ints(robot->fd, command, 3, distances);
    
        if (distances[2] < DISTANCE_OBS_IN_FRONT_OF)
        {
          signal_obstacle_front(commands_infos, position,
                                                    network_cond, distances[2]);
        }
        if (distances[2] < 20
              && distances[0] < DISTANCE_BYPASS
              && distances[1] < DISTANCE_BYPASS)
        {
          bypass_phase = 1;
          if (!is_beginning_defined)
          {
            is_beginning_defined = 1;
            begin_bypass_position = *position;
          }
          signal_begin_skip(commands_infos, network_cond);
              LOG_DEBUG("bleh5\n");
          mutex_and_send(robot, "mogo 1:7 2:-7\r",
                            "write mogo unsuccessful\n");
          right = 1;
        }
        else if (distances[0] > DISTANCE_TOO_NEAR)
        {
          bypass_phase = 1;
          if (!is_beginning_defined)
          {
            is_beginning_defined = 1;
            begin_bypass_position = *position;
          }
          signal_begin_skip(commands_infos, network_cond);
          signal_obstacle_right(commands_infos, position, network_cond,
                                                                distances[0]);
              LOG_DEBUG("bleh5.5\n");
          mutex_and_send(robot, "mogo 1:-7 2:7\r",
                            "write mogo unsuccessful\n");
          left = 1;
        }
        else if (distances[1] > DISTANCE_TOO_NEAR)
        {
          bypass_phase = 1;
          if (!is_beginning_defined)
          {
            is_beginning_defined = 1;
            begin_bypass_position = *position;
          }
          signal_begin_skip(commands_infos, network_cond);
          signal_obstacle_left(commands_infos, position, network_cond,
                                                                distances[1]);
              LOG_DEBUG("bleh6\n");
          mutex_and_send(robot, "mogo 1:7 2:-7\r",
                            "write mogo unsuccessful\n");
          right = 1;
        }
        else if (distances[0] > DISTANCE_BYPASS)
        {
          bypass_phase = 1;
          if (!is_beginning_defined)
          {
            is_beginning_defined = 1;
            begin_bypass_position = *position;
          }
          signal_begin_skip(commands_infos, network_cond);
          signal_obstacle_right(commands_infos, position, network_cond,
                                                                distances[0]);
              LOG_DEBUG("bleh7\n");
          mutex_and_send(robot, "mogo 1:10 2:7\r",
                            "write mogo unsuccessful\n");
          //left = 0;
        }
        else if (distances[1] > DISTANCE_BYPASS)
        {
          bypass_phase = 1;
          if (!is_beginning_defined)
          {
            is_beginning_defined = 1;
            begin_bypass_position = *position;
          }
          signal_begin_skip(commands_infos, network_cond);
          signal_obstacle_left(commands_infos, position, network_cond,
                                                                distances[1]);
              LOG_DEBUG("bleh8\n");
          mutex_and_send(robot, "mogo 1:7 2:10\r",
                            "write mogo unsuccessful\n");
          //right = 0;
        }
        //LOG_DEBUG("distances[0] :%d and left: %d\n", distances[0], left);
        //LOG_DEBUG("distances[1] :%d and left: %d\n", distances[1], right);
        else if (distances[0] < DISTANCE_BYPASS && distances[1] < DISTANCE_BYPASS
                                                                  && left == 1)
        {
          bypass_phase = 1;
          if (!is_beginning_defined)
          {
            is_beginning_defined = 1;
            begin_bypass_position = *position;
          }
          signal_begin_skip(commands_infos, network_cond);
              LOG_DEBUG("bleh9\n");
          mutex_and_send(robot, "mogo 1:7 2:-7\r",
                            "write mogo unsuccessful\n");
          return_towards_obs = 1;
          
        }
        else if (distances[1] < DISTANCE_BYPASS
                                && distances[0] < DISTANCE_BYPASS && right == 1)
        {
          bypass_phase = 1;
          if (!is_beginning_defined)
          {
            is_beginning_defined = 1;
            begin_bypass_position = *position;
          }
          signal_begin_skip(commands_infos, network_cond);
              LOG_DEBUG("bleh10\n");
          mutex_and_send(robot, "mogo 1:-7 2:7\r",
                            "write mogo unsuccessful\n");
          return_towards_obs = 1;
        }
        if (distances[0] < DISTANCE_BYPASS
                  && distances[1] < DISTANCE_BYPASS && bypass_phase == 1)
        {
          float angle = 270;
          
          if (position->y != begin_bypass_position.y)
            angle = atan((position->x - begin_bypass_position.x)
                                / (position->y - begin_bypass_position.y));
          LOG_DEBUG("angle : %f\n", angle);
          if (angle > -0.08 && angle < 0.08
                         && sqrt(pow(position->x - begin_bypass_position.x, 2)
                            + pow(position->y - begin_bypass_position.y,2)) > 20)
          {
            LOG_DEBUG("j'ai fini\n");
            bypass_phase = -1;
            
            if (abs(current_move.goal.t - position->t) < 4)
            {
              return_to_direction = 0;
            }

            if (return_to_direction == -1)
            {
              LOG_DEBUG("miaou\n");
              return_to_direction = 1;
              int a = (int)(current_move.goal.t - position->t + 360)%360;
              if(a > 180)
              {
                sprintf(command, "mogo 1:7 :-7\r");
              }
              else
              {
                sprintf(command, "mogo 1:-7 2:7\r");
              }
              mutex_and_send(robot,command,
                             "write mogo orientation unsuccesful\n");

            }
            signal_end_skip(commands_infos, network_cond);
            left = right = is_beginning_defined = 0;
            
          }
        }
      
        /*
        if (distances[2] < DISTANCE_OBS_IN_FRONT_OF && current_move.speed != 0)
        {
          signal_obstacle_front(commands_infos, position,
                                                    network_cond, distances[2]);
          if (distances[1] > DISTANCE_BYPASS && distances[0] > DISTANCE_BYPASS)
          {
            LOG_DEBUG("phase1 : les 2 côtés, recule\n");
            bypass_phase = 1;
            signal_begin_skip(commands_infos, network_cond);
            mutex_and_send(robot, "mogo 1:-7 2:-7\r",
                            "write mogo unsuccessful\n");
          }
          else if (distances[1] > DISTANCE_BYPASS
                                              && distances[0] < DISTANCE_BYPASS)
          {
            bypass_phase = 1;
            LOG_DEBUG("phase1 : côté gauche, tourne à droite\n");
            signal_begin_skip(commands_infos, network_cond);
            mutex_and_send(robot, "mogo 1:7 2:-7\r",
                            "write mogo unsuccessful\n");
            
            if (distances[1] > DISTANCE_BYPASS
                                            && distances[1] < DISTANCE_TOO_NEAR)
            {
              LOG_DEBUG("bleh1\n");
              mutex_and_send(robot, "mogo 1:7 2:7\r",
                            "write mogo unsuccessful\n");
            }
            else if (distances[1] > DISTANCE_TOO_NEAR)
            {
              LOG_DEBUG("bleh2\n");
              mutex_and_send(robot, "mogo 1:7 2:-7\r",
                            "write mogo unsuccessful\n");
            }
          }
          else if (distances[0] > DISTANCE_BYPASS
                                              && distances[1] < DISTANCE_BYPASS)
          {
            bypass_phase = 1;
            LOG_DEBUG("phase1 : côté droit, tourne à gauche\n");
            signal_begin_skip(commands_infos, network_cond);
            mutex_and_send(robot, "mogo 1:-7 2:7\r",
                            "write mogo unsuccessful\n");
            
            if (distances[0] > DISTANCE_BYPASS
                                            && distances[0] < DISTANCE_TOO_NEAR)
            {
              LOG_DEBUG("bleh3\n");
              mutex_and_send(robot, "mogo 1:7 2:7\r",
                            "write mogo unsuccessful\n");
            }
            else if (distances[0] > DISTANCE_TOO_NEAR)
            {
              LOG_DEBUG("bleh4\n");
              mutex_and_send(robot, "mogo 1:-7 2:7\r",
                            "write mogo unsuccessful\n");
            }
          }

        }
        else if (distances[2] > DISTANCE_OBS_IN_FRONT_OF && bypass_phase == 1
                                                && current_move.speed != 0)
        {
          float angle = atan((position->x - begin_bypass_position.x)
                      / (position->y - begin_bypass_position.y));
          if (angle > (begin_bypass_position.t - 5)
                && angle < (begin_bypass_position.t + 5))

          {
            bypass_phase = -1;
            LOG_DEBUG("phase2 : j'ai fini\n");
            signal_begin_dep(commands_infos, network_cond);
          }
          else if (distances[1] > DISTANCE_BYPASS
                                              && distances[0] > DISTANCE_BYPASS)
          {
            LOG_DEBUG("phase 2 : les 2 cotés, recule\n");
            mutex_and_send(robot, "mogo 1:-7 2:-7\r",
                            "write mogo unsuccessful\n");
          }
          else if (distances[1] > DISTANCE_BYPASS
                                              && distances[0] < DISTANCE_BYPASS)
          {
            LOG_DEBUG("phase 2 : coté gauche, va tout droit\n");
            mutex_and_send(robot, "mogo 1:7 2:7\r",
                            "write mogo unsuccessful\n");
          }
          else if (distances[1] < DISTANCE_TOO_NEAR && distances[1]
                            > DISTANCE_BYPASS && distances[0] < DISTANCE_BYPASS)
          {
            LOG_DEBUG("phase 2 : coté gauche, tourne a droite\n");
            mutex_and_send(robot, "mogo 1:-7 2:7\r",
                            "write mogo unsuccessful\n");
          }
          else if (distances[1] > DISTANCE_TOO_NEAR && distances[0]
                                                              < DISTANCE_BYPASS)
          {
            LOG_DEBUG("phase 2 : coté gauche, va a gauche\n");
            mutex_and_send(robot, "mogo 1:7 2:-7\r",
                            "write mogo unsuccessful\n");
          }
          else if (distances[0] > DISTANCE_BYPASS && distances[1]
                                                              < DISTANCE_BYPASS)
          {
            LOG_DEBUG("phase 2 : coté droit, va tout droit\n");
            mutex_and_send(robot, "mogo 1:7 2:7\r",
                            "write mogo unsuccessful\n");
          }
          else if (distances[0] < DISTANCE_TOO_NEAR && distances[0]
                            > DISTANCE_BYPASS && distances[1] < DISTANCE_BYPASS)
          {
            LOG_DEBUG("phase 2 : coté droit, va a gauche\n");
            mutex_and_send(robot, "mogo 1:7 2:-7\r",
                            "write mogo unsuccessful\n");
          }
          else if (distances[0] > DISTANCE_TOO_NEAR && distances[1]
                                                              < DISTANCE_BYPASS)
          {
            LOG_DEBUG("phase 2 : coté droit, va a droite\n");
            mutex_and_send(robot, "mogo 1:-7 2:7\r",
                            "write mogo unsuccessful\n");
          }
        }
        */


        // sinon, vérifier si on suit la bonne trajectoire
        ++count_dbg;
        //printf("%d\n", count_dbg);

      }

      // Wait some time or until new command set is signaled by network_thread
      if ((current_first_move != *first_move) ||(wait_time_cond(command_cond, robot, COMMAND_CHECK_INTERVAL) != ETIMEDOUT) )
      {
        // New set of commands
        pthread_cond_signal(position_cond);
        break;
      }
      if ((current_first_move != *first_move))
      {
        // New set of commands
        pthread_cond_signal(position_cond);
        break;
      }
    }
  }
  pthread_mutex_unlock(&robot->free);
}
Example #7
0
static void exit_handler(int sig)
{
   pthread_cond_signal(&sleepCond);
}
static void WaitUntilThreadSleep(std::atomic<pid_t>& pid) {
  while (pid == 0) {
    usleep(1000);
  }
  std::string filename = android::base::StringPrintf("/proc/%d/stat", pid.load());
  std::regex regex {R"(\s+S\s+)"};

  while (true) {
    std::string content;
    ASSERT_TRUE(android::base::ReadFileToString(filename, &content));
    if (std::regex_search(content, regex)) {
      break;
    }
    usleep(1000);
  }
}

struct RwlockWakeupHelperArg {
  pthread_rwlock_t lock;
  enum Progress {
    LOCK_INITIALIZED,
    LOCK_WAITING,
    LOCK_RELEASED,
    LOCK_ACCESSED
  };
  std::atomic<Progress> progress;
  std::atomic<pid_t> tid;
};

static void pthread_rwlock_reader_wakeup_writer_helper(RwlockWakeupHelperArg* arg) {
  arg->tid = gettid();
  ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress);
  arg->progress = RwlockWakeupHelperArg::LOCK_WAITING;

  ASSERT_EQ(EBUSY, pthread_rwlock_trywrlock(&arg->lock));
  ASSERT_EQ(0, pthread_rwlock_wrlock(&arg->lock));
  ASSERT_EQ(RwlockWakeupHelperArg::LOCK_RELEASED, arg->progress);
  ASSERT_EQ(0, pthread_rwlock_unlock(&arg->lock));

  arg->progress = RwlockWakeupHelperArg::LOCK_ACCESSED;
}

TEST(pthread, pthread_rwlock_reader_wakeup_writer) {
  RwlockWakeupHelperArg wakeup_arg;
  ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, NULL));
  ASSERT_EQ(0, pthread_rwlock_rdlock(&wakeup_arg.lock));
  wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
  wakeup_arg.tid = 0;

  pthread_t thread;
  ASSERT_EQ(0, pthread_create(&thread, NULL,
    reinterpret_cast<void* (*)(void*)>(pthread_rwlock_reader_wakeup_writer_helper), &wakeup_arg));
  WaitUntilThreadSleep(wakeup_arg.tid);
  ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress);

  wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_RELEASED;
  ASSERT_EQ(0, pthread_rwlock_unlock(&wakeup_arg.lock));

  ASSERT_EQ(0, pthread_join(thread, NULL));
  ASSERT_EQ(RwlockWakeupHelperArg::LOCK_ACCESSED, wakeup_arg.progress);
  ASSERT_EQ(0, pthread_rwlock_destroy(&wakeup_arg.lock));
}

static void pthread_rwlock_writer_wakeup_reader_helper(RwlockWakeupHelperArg* arg) {
  arg->tid = gettid();
  ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress);
  arg->progress = RwlockWakeupHelperArg::LOCK_WAITING;

  ASSERT_EQ(EBUSY, pthread_rwlock_tryrdlock(&arg->lock));
  ASSERT_EQ(0, pthread_rwlock_rdlock(&arg->lock));
  ASSERT_EQ(RwlockWakeupHelperArg::LOCK_RELEASED, arg->progress);
  ASSERT_EQ(0, pthread_rwlock_unlock(&arg->lock));

  arg->progress = RwlockWakeupHelperArg::LOCK_ACCESSED;
}

TEST(pthread, pthread_rwlock_writer_wakeup_reader) {
  RwlockWakeupHelperArg wakeup_arg;
  ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, NULL));
  ASSERT_EQ(0, pthread_rwlock_wrlock(&wakeup_arg.lock));
  wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_INITIALIZED;
  wakeup_arg.tid = 0;

  pthread_t thread;
  ASSERT_EQ(0, pthread_create(&thread, NULL,
    reinterpret_cast<void* (*)(void*)>(pthread_rwlock_writer_wakeup_reader_helper), &wakeup_arg));
  WaitUntilThreadSleep(wakeup_arg.tid);
  ASSERT_EQ(RwlockWakeupHelperArg::LOCK_WAITING, wakeup_arg.progress);

  wakeup_arg.progress = RwlockWakeupHelperArg::LOCK_RELEASED;
  ASSERT_EQ(0, pthread_rwlock_unlock(&wakeup_arg.lock));

  ASSERT_EQ(0, pthread_join(thread, NULL));
  ASSERT_EQ(RwlockWakeupHelperArg::LOCK_ACCESSED, wakeup_arg.progress);
  ASSERT_EQ(0, pthread_rwlock_destroy(&wakeup_arg.lock));
}

static int g_once_fn_call_count = 0;
static void OnceFn() {
  ++g_once_fn_call_count;
}

TEST(pthread, pthread_once_smoke) {
  pthread_once_t once_control = PTHREAD_ONCE_INIT;
  ASSERT_EQ(0, pthread_once(&once_control, OnceFn));
  ASSERT_EQ(0, pthread_once(&once_control, OnceFn));
  ASSERT_EQ(1, g_once_fn_call_count);
}

static std::string pthread_once_1934122_result = "";

static void Routine2() {
  pthread_once_1934122_result += "2";
}

static void Routine1() {
  pthread_once_t once_control_2 = PTHREAD_ONCE_INIT;
  pthread_once_1934122_result += "1";
  pthread_once(&once_control_2, &Routine2);
}

TEST(pthread, pthread_once_1934122) {
  // Very old versions of Android couldn't call pthread_once from a
  // pthread_once init routine. http://b/1934122.
  pthread_once_t once_control_1 = PTHREAD_ONCE_INIT;
  ASSERT_EQ(0, pthread_once(&once_control_1, &Routine1));
  ASSERT_EQ("12", pthread_once_1934122_result);
}

static int g_atfork_prepare_calls = 0;
static void AtForkPrepare1() { g_atfork_prepare_calls = (g_atfork_prepare_calls << 4) | 1; }
static void AtForkPrepare2() { g_atfork_prepare_calls = (g_atfork_prepare_calls << 4) | 2; }
static int g_atfork_parent_calls = 0;
static void AtForkParent1() { g_atfork_parent_calls = (g_atfork_parent_calls << 4) | 1; }
static void AtForkParent2() { g_atfork_parent_calls = (g_atfork_parent_calls << 4) | 2; }
static int g_atfork_child_calls = 0;
static void AtForkChild1() { g_atfork_child_calls = (g_atfork_child_calls << 4) | 1; }
static void AtForkChild2() { g_atfork_child_calls = (g_atfork_child_calls << 4) | 2; }

TEST(pthread, pthread_atfork_smoke) {
  ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
  ASSERT_EQ(0, pthread_atfork(AtForkPrepare2, AtForkParent2, AtForkChild2));

  int pid = fork();
  ASSERT_NE(-1, pid) << strerror(errno);

  // Child and parent calls are made in the order they were registered.
  if (pid == 0) {
    ASSERT_EQ(0x12, g_atfork_child_calls);
    _exit(0);
  }
  ASSERT_EQ(0x12, g_atfork_parent_calls);

  // Prepare calls are made in the reverse order.
  ASSERT_EQ(0x21, g_atfork_prepare_calls);
}

TEST(pthread, pthread_attr_getscope) {
  pthread_attr_t attr;
  ASSERT_EQ(0, pthread_attr_init(&attr));

  int scope;
  ASSERT_EQ(0, pthread_attr_getscope(&attr, &scope));
  ASSERT_EQ(PTHREAD_SCOPE_SYSTEM, scope);
}

TEST(pthread, pthread_condattr_init) {
  pthread_condattr_t attr;
  pthread_condattr_init(&attr);

  clockid_t clock;
  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
  ASSERT_EQ(CLOCK_REALTIME, clock);

  int pshared;
  ASSERT_EQ(0, pthread_condattr_getpshared(&attr, &pshared));
  ASSERT_EQ(PTHREAD_PROCESS_PRIVATE, pshared);
}

TEST(pthread, pthread_condattr_setclock) {
  pthread_condattr_t attr;
  pthread_condattr_init(&attr);

  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_REALTIME));
  clockid_t clock;
  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
  ASSERT_EQ(CLOCK_REALTIME, clock);

  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
  ASSERT_EQ(CLOCK_MONOTONIC, clock);

  ASSERT_EQ(EINVAL, pthread_condattr_setclock(&attr, CLOCK_PROCESS_CPUTIME_ID));
}

TEST(pthread, pthread_cond_broadcast__preserves_condattr_flags) {
#if defined(__BIONIC__)
  pthread_condattr_t attr;
  pthread_condattr_init(&attr);

  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
  ASSERT_EQ(0, pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED));

  pthread_cond_t cond_var;
  ASSERT_EQ(0, pthread_cond_init(&cond_var, &attr));

  ASSERT_EQ(0, pthread_cond_signal(&cond_var));
  ASSERT_EQ(0, pthread_cond_broadcast(&cond_var));

  attr = static_cast<pthread_condattr_t>(*reinterpret_cast<uint32_t*>(cond_var.__private));
  clockid_t clock;
  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
  ASSERT_EQ(CLOCK_MONOTONIC, clock);
  int pshared;
  ASSERT_EQ(0, pthread_condattr_getpshared(&attr, &pshared));
  ASSERT_EQ(PTHREAD_PROCESS_SHARED, pshared);
#else  // !defined(__BIONIC__)
  GTEST_LOG_(INFO) << "This tests a bionic implementation detail.\n";
#endif  // !defined(__BIONIC__)
}

class pthread_CondWakeupTest : public ::testing::Test {
 protected:
  pthread_mutex_t mutex;
  pthread_cond_t cond;

  enum Progress {
    INITIALIZED,
    WAITING,
    SIGNALED,
    FINISHED,
  };
  std::atomic<Progress> progress;
  pthread_t thread;

 protected:
  virtual void SetUp() {
    ASSERT_EQ(0, pthread_mutex_init(&mutex, NULL));
    ASSERT_EQ(0, pthread_cond_init(&cond, NULL));
    progress = INITIALIZED;
    ASSERT_EQ(0,
      pthread_create(&thread, NULL, reinterpret_cast<void* (*)(void*)>(WaitThreadFn), this));
  }

  virtual void TearDown() {
    ASSERT_EQ(0, pthread_join(thread, NULL));
    ASSERT_EQ(FINISHED, progress);
    ASSERT_EQ(0, pthread_cond_destroy(&cond));
    ASSERT_EQ(0, pthread_mutex_destroy(&mutex));
  }

  void SleepUntilProgress(Progress expected_progress) {
    while (progress != expected_progress) {
      usleep(5000);
    }
    usleep(5000);
  }

 private:
  static void WaitThreadFn(pthread_CondWakeupTest* test) {
    ASSERT_EQ(0, pthread_mutex_lock(&test->mutex));
    test->progress = WAITING;
    while (test->progress == WAITING) {
      ASSERT_EQ(0, pthread_cond_wait(&test->cond, &test->mutex));
    }
    ASSERT_EQ(SIGNALED, test->progress);
    test->progress = FINISHED;
    ASSERT_EQ(0, pthread_mutex_unlock(&test->mutex));
  }
};

TEST_F(pthread_CondWakeupTest, signal) {
  SleepUntilProgress(WAITING);
  progress = SIGNALED;
  pthread_cond_signal(&cond);
}
Example #9
0
void ConditionImpl::signal()
{
    int rc = pthread_cond_signal( &_cond );
    if( rc != 0 )
        throw SystemError( rc, "pthread_cond_signal failed");
}
Example #10
0
void equeue_sema_signal(equeue_sema_t *s) {
    pthread_mutex_lock(&s->mutex);
    s->signal = true;
    pthread_cond_signal(&s->cond);
    pthread_mutex_unlock(&s->mutex);
}
Example #11
0
// --------------------------------------------------------------------------------------  FUNCTION
// --------------------------------------------------------------------------------------  FUNCTION
void Monitor::Signal() const
{
    int err = pthread_cond_signal(&mCondition);
    HandleErrno(err, "pthread_cond_signal");
}
Example #12
0
int main(){
    int LISTEN_BACKLOG=10;
    int sfd=socket(AF_INET,SOCK_STREAM,0);	
    struct sockaddr_in my_addr, their_addr;
    if(sfd==-1){
	fprintf(stderr,"socket error\n");
	exit(1);
    }
    //struct sockaddr addr;
    my_addr.sin_family=AF_INET;                
    my_addr.sin_port = htons(9100);            
    my_addr.sin_addr.s_addr = INADDR_ANY; 
    bzero(&(my_addr.sin_zero), 8);               
    if(bind(sfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1){
	fprintf(stderr,"bind error\n");
	exit(1);
    }
    if(listen(sfd,LISTEN_BACKLOG)==-1){
	fprintf(stderr,"listen error\n");
	exit(1);
    }
	int nfds;
	m_epollfd=epoll_create(QUEUELEN);
	struct epoll_event m_epollev[QUEUELEN];
	struct epoll_event ev;
	ev.data.fd=sfd;
	ev.events=EPOLLIN|EPOLLET;
	epoll_ctl(m_epollfd,EPOLL_CTL_ADD,sfd,&ev);

	int sockfd=0;int i=0;
	int sock;
	socklen_t sin_size;
	   
	thread_make(THREAD_NUM);

	while(1){
//	epoll
	//if recv,lock sockArray[sockRear++]=sock; unlock;
	//read rear=(rear+1)%QUEUELEN	sockArray[rear]=sock;
	nfds=epoll_wait(m_epollfd,m_epollev,QUEUELEN,-1);
	for(i=0;i<nfds;i++)
	{
		sockfd=m_epollev[i].data.fd;
		struct epoll_event _event=m_epollev[i];
		if(sfd==sockfd)
		{
			//accept
			sin_size=sizeof(struct sockaddr);
			sock=accept(sfd,(void*)&their_addr,&sin_size);
			ev.data.fd=sock;
			ev.events=EPOLLIN|EPOLLET;
			epoll_ctl(m_epollfd,EPOLL_CTL_ADD,sock,&ev);
		}
		else if(_event.events&EPOLLIN)
		{
		//lock
			pthread_mutex_lock(&mlock);
			if(sockFront==((sockRear+1)%QUEUELEN))
			{
				printf("GET TO THE MAX LIMIT %d\n",QUEUELEN);
				pthread_mutex_unlock(&mlock);
				continue;
			}
			sockRear=(sockRear+1)%QUEUELEN;
			sockArray[sockRear]=sockfd;
			printf("here we are %d\n",sockfd);
			pthread_mutex_unlock(&mlock);
			pthread_cond_signal(&m_condlock);	
		//unlock
		}
		else
			printf("epoll:else\n");
	}
    }
} 
Example #13
0
void *_forward_thread(void *arg)
{
	forward_msg_t *fwd_msg = (forward_msg_t *)arg;
	Buf buffer = init_buf(fwd_msg->buf_len);
	List ret_list = NULL;
	slurm_fd_t fd = -1;
	ret_data_info_t *ret_data_info = NULL;
	char *name = NULL;
	hostlist_t hl = hostlist_create(fwd_msg->header.forward.nodelist);
	slurm_addr_t addr;
	char *buf = NULL;
	int steps = 0;
	int start_timeout = fwd_msg->timeout;

	/* repeat until we are sure the message was sent */
	while((name = hostlist_shift(hl))) {
		if(slurm_conf_get_addr(name, &addr) == SLURM_ERROR) {
			error("forward_thread: can't find address for host "
			      "%s, check slurm.conf", name);
			slurm_mutex_lock(fwd_msg->forward_mutex);
			mark_as_failed_forward(&fwd_msg->ret_list, name,
					       SLURM_UNKNOWN_FORWARD_ADDR);
 			free(name);
			if (hostlist_count(hl) > 0) {
				slurm_mutex_unlock(fwd_msg->forward_mutex);
				continue;
			}
			goto cleanup;
		}
		if ((fd = slurm_open_msg_conn(&addr)) < 0) {
			error("forward_thread to %s: %m", name);

			slurm_mutex_lock(fwd_msg->forward_mutex);
			mark_as_failed_forward(
				&fwd_msg->ret_list, name,
				SLURM_COMMUNICATIONS_CONNECTION_ERROR);
			free(name);
			if (hostlist_count(hl) > 0) {
				slurm_mutex_unlock(fwd_msg->forward_mutex);
				continue;
			}
			goto cleanup;
		}
		buf = hostlist_ranged_string_xmalloc(hl);

		xfree(fwd_msg->header.forward.nodelist);
		fwd_msg->header.forward.nodelist = buf;
		fwd_msg->header.forward.cnt = hostlist_count(hl);
		/* info("sending %d forwards (%s) to %s", */
/* 		     fwd_msg->header.forward.cnt, */
/* 		     fwd_msg->header.forward.nodelist, name); */
		if (fwd_msg->header.forward.nodelist[0]) {
			debug3("forward: send to %s along with %s",
			       name, fwd_msg->header.forward.nodelist);
		} else
			debug3("forward: send to %s ", name);

		pack_header(&fwd_msg->header, buffer);

		/* add forward data to buffer */
		if (remaining_buf(buffer) < fwd_msg->buf_len) {
			buffer->size += (fwd_msg->buf_len + BUF_SIZE);
			xrealloc(buffer->head, buffer->size);
		}
		if (fwd_msg->buf_len) {
			memcpy(&buffer->head[buffer->processed],
			       fwd_msg->buf, fwd_msg->buf_len);
			buffer->processed += fwd_msg->buf_len;
		}

		/*
		 * forward message
		 */
		if(_slurm_msg_sendto(fd,
				     get_buf_data(buffer),
				     get_buf_offset(buffer),
				     SLURM_PROTOCOL_NO_SEND_RECV_FLAGS ) < 0) {
			error("forward_thread: slurm_msg_sendto: %m");

			slurm_mutex_lock(fwd_msg->forward_mutex);
			mark_as_failed_forward(&fwd_msg->ret_list, name,
					       errno);
			free(name);
			if(hostlist_count(hl) > 0) {
				free_buf(buffer);
				buffer = init_buf(fwd_msg->buf_len);
				slurm_mutex_unlock(fwd_msg->forward_mutex);
				slurm_close_accepted_conn(fd);
				fd = -1;
				continue;
			}
			goto cleanup;
		}

		if ((fwd_msg->header.msg_type == REQUEST_SHUTDOWN) ||
		    (fwd_msg->header.msg_type == REQUEST_RECONFIGURE) ||
		    (fwd_msg->header.msg_type == REQUEST_REBOOT_NODES)) {
			slurm_mutex_lock(fwd_msg->forward_mutex);
			ret_data_info = xmalloc(sizeof(ret_data_info_t));
			list_push(fwd_msg->ret_list, ret_data_info);
			ret_data_info->node_name = xstrdup(name);
			free(name);
			while((name = hostlist_shift(hl))) {
				ret_data_info =
					xmalloc(sizeof(ret_data_info_t));
				list_push(fwd_msg->ret_list, ret_data_info);
				ret_data_info->node_name = xstrdup(name);
				free(name);
			}
			goto cleanup;
		}

		if(fwd_msg->header.forward.cnt > 0) {
			static int message_timeout = -1;
			if (message_timeout < 0)
				message_timeout =
					slurm_get_msg_timeout() * 1000;
			steps = (fwd_msg->header.forward.cnt+1) /
				slurm_get_tree_width();
			fwd_msg->timeout = (message_timeout*steps);
/* 			info("got %d * %d = %d", message_timeout, steps, fwd_msg->timeout); */
			steps++;
			fwd_msg->timeout += (start_timeout*steps);
/* 			info("now  + %d*%d = %d", start_timeout, steps, fwd_msg->timeout); */
		}

		ret_list = slurm_receive_msgs(fd, steps, fwd_msg->timeout);
		/* info("sent %d forwards got %d back", */
/* 		     fwd_msg->header.forward.cnt, list_count(ret_list)); */

		if(!ret_list || (fwd_msg->header.forward.cnt != 0
				 && list_count(ret_list) <= 1)) {
			slurm_mutex_lock(fwd_msg->forward_mutex);
			mark_as_failed_forward(&fwd_msg->ret_list, name,
					       errno);
			free(name);
			if(ret_list)
				list_destroy(ret_list);
			if (hostlist_count(hl) > 0) {
				free_buf(buffer);
				buffer = init_buf(fwd_msg->buf_len);
				slurm_mutex_unlock(fwd_msg->forward_mutex);
				slurm_close_accepted_conn(fd);
				fd = -1;
				continue;
			}
			goto cleanup;
		} else if((fwd_msg->header.forward.cnt+1)
			  != list_count(ret_list)) {
			/* this should never be called since the above
			   should catch the failed forwards and pipe
			   them back down, but this is here so we
			   never have to worry about a locked
			   mutex */
			ListIterator itr = NULL;
			char *tmp = NULL;
			int first_node_found = 0;
			hostlist_iterator_t host_itr
				= hostlist_iterator_create(hl);
			error("We shouldn't be here.  We forwarded to %d "
			      "but only got %d back",
			      (fwd_msg->header.forward.cnt+1),
			      list_count(ret_list));
			while((tmp = hostlist_next(host_itr))) {
				int node_found = 0;
				itr = list_iterator_create(ret_list);
				while((ret_data_info = list_next(itr))) {
					if(!ret_data_info->node_name) {
						first_node_found = 1;
						ret_data_info->node_name =
							xstrdup(name);
					}
					if(!strcmp(tmp,
						   ret_data_info->node_name)) {
						node_found = 1;
						break;
					}
				}
				list_iterator_destroy(itr);
				if(!node_found) {
					mark_as_failed_forward(
						&fwd_msg->ret_list,
						tmp,
						SLURM_COMMUNICATIONS_CONNECTION_ERROR);
				}
				free(tmp);
			}
			hostlist_iterator_destroy(host_itr);
			if(!first_node_found) {
				mark_as_failed_forward(&fwd_msg->ret_list,
						       name,
						       SLURM_COMMUNICATIONS_CONNECTION_ERROR);
			}
		}
		break;
	}
	slurm_mutex_lock(fwd_msg->forward_mutex);
	if(ret_list) {
		while((ret_data_info = list_pop(ret_list)) != NULL) {
			if(!ret_data_info->node_name) {
				ret_data_info->node_name = xstrdup(name);
			}
			list_push(fwd_msg->ret_list, ret_data_info);
			debug3("got response from %s",
			       ret_data_info->node_name);
		}
		list_destroy(ret_list);
	}
	free(name);
cleanup:
	if ((fd >= 0) && slurm_close_accepted_conn(fd) < 0)
		error ("close(%d): %m", fd);
	hostlist_destroy(hl);
	destroy_forward(&fwd_msg->header.forward);
	free_buf(buffer);
	pthread_cond_signal(fwd_msg->notify);
	slurm_mutex_unlock(fwd_msg->forward_mutex);

	return (NULL);
}
Example #14
0
void *_fwd_tree_thread(void *arg)
{
	fwd_tree_t *fwd_tree = (fwd_tree_t *)arg;
	List ret_list = NULL;
	char *name = NULL;
	char *buf = NULL;
	slurm_msg_t send_msg;

	slurm_msg_t_init(&send_msg);
	send_msg.msg_type = fwd_tree->orig_msg->msg_type;
	send_msg.data = fwd_tree->orig_msg->data;

	/* repeat until we are sure the message was sent */
	while ((name = hostlist_shift(fwd_tree->tree_hl))) {
		if (slurm_conf_get_addr(name, &send_msg.address)
		    == SLURM_ERROR) {
			error("fwd_tree_thread: can't find address for host "
			      "%s, check slurm.conf", name);
			slurm_mutex_lock(fwd_tree->tree_mutex);
			mark_as_failed_forward(&fwd_tree->ret_list, name,
					       SLURM_UNKNOWN_FORWARD_ADDR);
 			pthread_cond_signal(fwd_tree->notify);
			slurm_mutex_unlock(fwd_tree->tree_mutex);
			free(name);

			continue;
		}

		send_msg.forward.timeout = fwd_tree->timeout;
		if((send_msg.forward.cnt = hostlist_count(fwd_tree->tree_hl))) {
			buf = hostlist_ranged_string_xmalloc(
					fwd_tree->tree_hl);
			send_msg.forward.nodelist = buf;
		} else
			send_msg.forward.nodelist = NULL;

		if (send_msg.forward.nodelist && send_msg.forward.nodelist[0]) {
			debug3("Tree sending to %s along with %s",
			       name, send_msg.forward.nodelist);
		} else
			debug3("Tree sending to %s", name);

		ret_list = slurm_send_addr_recv_msgs(&send_msg, name,
						     fwd_tree->timeout);

		xfree(send_msg.forward.nodelist);

		if(ret_list) {
			slurm_mutex_lock(fwd_tree->tree_mutex);
			list_transfer(fwd_tree->ret_list, ret_list);
			pthread_cond_signal(fwd_tree->notify);
			slurm_mutex_unlock(fwd_tree->tree_mutex);
			list_destroy(ret_list);
		} else {
			/* This should never happen (when this was
			   written slurm_send_addr_recv_msgs always
			   returned a list */
			error("fwd_tree_thread: no return list given from "
			      "slurm_send_addr_recv_msgs spawned for %s",
			      name);
			slurm_mutex_lock(fwd_tree->tree_mutex);
			mark_as_failed_forward(
				&fwd_tree->ret_list, name,
				SLURM_COMMUNICATIONS_CONNECTION_ERROR);
 			pthread_cond_signal(fwd_tree->notify);
			slurm_mutex_unlock(fwd_tree->tree_mutex);
			free(name);

			continue;
		}

		free(name);

		/* check for error and try again */
		if(errno == SLURM_COMMUNICATIONS_CONNECTION_ERROR)
 			continue;

		break;
	}

	_destroy_tree_fwd(fwd_tree);

	return NULL;
}
Example #15
0
 void TwoQStrategy::release(uint64_t id) {
     lockPreserved();
     _preserved[id] = false;
     unlockPreserved();
     pthread_cond_signal(&_preserved_changed);
 }
Example #16
0
static boolean msg_bus_post_msg(mct_bus_t *bus, mct_bus_msg_t *bus_msg)
{
  mct_bus_msg_t *local_msg;
  int post_msg = FALSE;
  unsigned int payload_size;

  if (!bus_msg) {
    ALOGE("%s:%d NULL ptr", __func__, __LINE__);
    goto error_2;
  }

  if (bus->bus_queue->length > MAX_MCT_BUS_QUEUE_LENGTH) {
      pthread_mutex_lock(&bus->bus_msg_q_lock);
      mct_bus_queue_flush(bus);
      ALOGE("%s : Discard the bus msg's that got stagnated in the queue\n",__func__);
      pthread_mutex_unlock(&bus->bus_msg_q_lock);
      return TRUE;
  }

  CDBG("%s:type=%d", __func__, bus_msg->type);

  switch (bus_msg->type) {
    case MCT_BUS_MSG_ISP_SOF:
      payload_size = sizeof(mct_bus_msg_isp_sof_t);
      if (bus->thread_run == 1) {
        pthread_mutex_lock(&bus->bus_sof_msg_lock);
        pthread_cond_signal(&bus->bus_sof_msg_cond);
        pthread_mutex_unlock(&bus->bus_sof_msg_lock);
      }
      break;
    case MCT_BUS_MSG_Q3A_AF_STATUS:
      payload_size = sizeof(mct_bus_msg_af_status_t);
      break;
    case MCT_BUS_MSG_ASD_HDR_SCENE_STATUS:
      payload_size = sizeof(mct_bus_msg_asd_hdr_status_t);
      break;
    case MCT_BUS_MSG_FACE_INFO:
      payload_size = sizeof(cam_face_detection_data_t);
      break;
    case MCT_BUS_MSG_HIST_STATS_INFO:
      payload_size = sizeof(cam_hist_stats_t);
      break;
    case MCT_BUS_MSG_PREPARE_HW_DONE:
      payload_size = sizeof(cam_prep_snapshot_state_t);
      break;
    case MCT_BUS_MSG_ZSL_TAKE_PICT_DONE:
      payload_size = sizeof(cam_frame_idx_range_t);
      break;
    case MCT_BUS_MSG_SET_SENSOR_INFO:
      payload_size = sizeof(mct_bus_msg_sensor_metadata_t);
      break;
    case MCT_BUS_MSG_SET_STATS_AEC_INFO:
      payload_size = bus_msg->size;
      break;
    case MCT_BUS_MSG_SET_ISP_GAMMA_INFO:
    case MCT_BUS_MSG_SET_ISP_STATS_AWB_INFO:
      payload_size = bus_msg->size;
      break;
   case MCT_BUS_MSG_ISP_STREAM_CROP:
      payload_size = sizeof(mct_bus_msg_stream_crop_t);
      break;
   case MCT_BUS_MSG_SET_AEC_STATE:
      payload_size = sizeof(int32_t);
      break;
   case MCT_BUS_MSG_SET_AEC_PRECAPTURE_ID:
      payload_size = sizeof(int32_t);
      break;
   case MCT_BUS_MSG_SET_AEC_RESET:
      payload_size = 0;
      break;
   case MCT_BUS_MSG_SET_AF_STATE:
      payload_size = sizeof(int32_t);
      break;
   case MCT_BUS_MSG_SET_AF_TRIGGER_ID:
      payload_size = sizeof(int32_t);
    case MCT_BUS_MSG_AUTO_SCENE_DECISION:
      payload_size = sizeof(mct_bus_msg_asd_decision_t);
      break;
   case MCT_BUS_MSG_ERROR_MESSAGE:
      payload_size = sizeof(mct_bus_msg_error_message_t);
      break;
   case MCT_BUS_MSG_AE_INFO:
      payload_size = sizeof(cam_ae_params_t);
      break;
   case MCT_BUS_MSG_AWB_INFO:
      payload_size = sizeof(cam_awb_params_t);
      break;
    case MCT_BUS_MSG_AE_EXIF_DEBUG_INFO:
       payload_size = sizeof(cam_ae_exif_debug_t);
       break;
    case MCT_BUS_MSG_AWB_EXIF_DEBUG_INFO:
       payload_size = sizeof(cam_awb_exif_debug_t);
       break;
   case MCT_BUS_MSG_AF_EXIF_DEBUG_INFO:
       payload_size = sizeof(cam_af_exif_debug_t);
       break;
   case MCT_BUS_MSG_ASD_EXIF_DEBUG_INFO:
       payload_size = sizeof(cam_asd_exif_debug_t);
       break;
   case MCT_BUS_MSG_STATS_EXIF_DEBUG_INFO:
       payload_size = sizeof(cam_stats_buffer_exif_debug_t);
       break;
   case MCT_BUS_MSG_SENSOR_INFO:
      payload_size = sizeof(cam_sensor_params_t);
      break;
   case MCT_BUS_MSG_SEND_HW_ERROR:
      payload_size = 0;
      post_msg = TRUE;
      pthread_mutex_lock(&bus->bus_msg_q_lock);
      mct_bus_queue_flush(bus);
      pthread_mutex_unlock(&bus->bus_msg_q_lock);
      break;
   case MCT_BUS_MSG_SENSOR_STARTING:
      start_sof_check_thread(bus);
      return TRUE;
      break;
   case MCT_BUS_MSG_SENSOR_STOPPING:
      stop_sof_check_thread(bus);
      return TRUE;
   case MCT_BUS_MSG_SENSOR_AF_STATUS:
      payload_size = sizeof(mct_bus_msg_af_status_t);
      break;
   case MCT_BUS_MSG_META_VALID:
      payload_size = sizeof(mct_bus_msg_meta_valid);
      break;
   /* bus msg for 3a update */
   case MCT_BUS_MSG_AE_EZTUNING_INFO:
   case MCT_BUS_MSG_AWB_EZTUNING_INFO:
   case MCT_BUS_MSG_AF_EZTUNING_INFO:
   case MCT_BUS_MSG_AF_MOBICAT_INFO:
      payload_size = bus_msg->size;
      break;
   case MCT_BUS_MSG_ISP_CHROMATIX_LITE:
   case MCT_BUS_MSG_PP_CHROMATIX_LITE:
      payload_size = bus_msg->size;
      break;
   case MCT_BUS_MSG_ISP_META:
      payload_size = bus_msg->size;
      break;
   case MCT_BUS_MSG_SENSOR_META:
      payload_size = bus_msg->size;
      break;
   case MCT_BUS_MSG_PREPARE_HDR_ZSL_DONE:
      payload_size = sizeof(cam_prep_snapshot_state_t);
      break;
   case MCT_BUS_MSG_REPROCESS_STAGE_DONE:
      payload_size = 0;
      post_msg = TRUE;
      break;
   case MCT_BUS_MSG_SEND_EZTUNE_EVT:
      payload_size = 0;
      post_msg = TRUE;
      break;
   default:
      CDBG("%s: bus_msg type is not valid", __func__);
      goto error_2;
  }
  if (bus->msg_to_send_metadata == bus_msg->type) {
    post_msg = TRUE;
  }

  local_msg = malloc(sizeof(mct_bus_msg_t));

  if (!local_msg) {
    ALOGE("%s:%d Can't allocate memory", __func__, __LINE__);
    goto error_2;
  }

  local_msg->sessionid = bus_msg->sessionid;
  local_msg->type = bus_msg->type;
  local_msg->size = bus_msg->size;

  if (payload_size) {
    local_msg->msg = malloc(payload_size);
    if (!local_msg->msg) {
      ALOGE("%s:%d Can't allocate memory", __func__, __LINE__);
      goto error_1;
    }
    memcpy(local_msg->msg, bus_msg->msg, payload_size);
  } else {
    local_msg->msg = NULL;
  }

  /* Push message to Media Controller/Pipeline BUS Queue
   * and post signal to Media Controller */
  pthread_mutex_lock(&bus->bus_msg_q_lock);
  mct_queue_push_tail(bus->bus_queue, local_msg);
  pthread_mutex_unlock(&bus->bus_msg_q_lock);

  if (post_msg) {
    pthread_mutex_lock(bus->mct_mutex);
    bus->bus_cmd_q_flag = TRUE;
    pthread_cond_signal(bus->mct_cond);
    pthread_mutex_unlock(bus->mct_mutex);
  }


  return TRUE;

error_1:
  free(local_msg);
error_2:
  return FALSE;
}
Example #17
0
File: main.c Project: bochf/testing
/* ========================================================================= */
int main(int argc, char *argv[])
{
   struct options *clo;            /* Command line options                   */
   struct proot *p;                /* Base of all provider/pitem data        */
   struct config *cfg;             /* Config file input (parsed to struct)   */
   struct prov_name *pn;
   struct thread_root *tr;
   struct provider *hot_provider;
   struct provider *this_provider; /* Used to walk the provider list */
   struct sighandler_arg *timerc;  /* This is the timer cond variable */

   int first_iteration;
   int sdivisor;      /* Divisor calculated for per-second averaging         */
   int stemp;         /* Temp variable used for sdivisor calculations        */
   int mfail; /* Used in multiple error/fail situations */

   /* Used for simple stat notification (if verbose) */
   int provcnt;
   int apcnt; /* Active provider count */
   int prrv; /* provider registration rv (used to check registrations) */

   /* Used to print (reformat) parts of error messages */
   char errstr[80];

   /* Used for the writer */
   int (*writer_finish)(void *data_handle);
   void *writer_data;
   int writer_state;

   /* Times used for the run_for config file option */
   time_t stop_at;
   time_t time_now;


   int tc;
   /* Used for $ARG substitution */
   int ascount; /* Used as basic stats on substitution counts - for reporting */
   char *argsub; 
   char *argval;
   int   argnum;
   char *before_arg;
   char *after_arg;
   char *rebuilt_arg;
   int i, j;

   /* Set default error message destination to stderr */
   errorto = ERROR_MSG_STDERR;

   if ( NULL == (clo = ReadOptions(argc, argv)) )
      return(1);

   if ( clo->bHelp )
      return(help());

   if ( clo->bAbout )
      return(about());

   if ( clo->bError )
      return(1);

   /* Initialize our provider root */
   p = Providers();

   /* Register the provider(s) */
   prrv =  CoreRegister(p); 
   prrv += AllOSRegister(p);
   prrv += CmnPRegister(p);

   if ( prrv )
   {
      error_msg("ERROR: Failed to register a provider.");
      return(1);
   }

   /* Handle all the potential list options (-l,-p,-d) */
   /* Dump providers (if asked) */
   if ( clo->bListProv )
   {
      this_provider = p->prov_list;
      while( this_provider )
      {
         printf("%s\n", this_provider->name);
         this_provider = this_provider->next;
      }
      fflush(stdout);
      return(0);
   }

   /* Dump data items for a provider (if asked) */
   if ( clo->bListPD )
   {
      this_provider = p->prov_list;
      while( this_provider )
      {
         if ( 0 == strcmp(this_provider->name, clo->provider) )
         {
            /* Match found */
            printf("%s\n", this_provider->name);
            this_provider->listavail(clo->bListTypes);
            fflush(stdout);
            return(0);
         }
         this_provider = this_provider->next;
      }
      error_msg("ERROR: No provider matches \"%s\".", clo->provider);
      fflush(stdout);
      return(1);
   }

   /* Lis all data items from all providers (if asked) */
   if ( clo->bListAllD )
   {
      DumpPItemList(p, clo->bListTypes);
      return(0);
   }

   /* We are in it for the long haul - set go to true */
   go = 1;
   tt = 0; /* No ticks at this time */

   if ( NULL == clo->confile )
   {
      error_msg("ERROR: No config file was specified. Unable to continue.");
      return(1);
   }

   /* Read in the config file */
   if ( NULL == (cfg = ReadConfigFile(clo->confile)) )
      return(1);

   /* Validate some DANGER! conditions */
   mfail = 0;
   if (( 0 == clo->bDanger ) && ( DANGER_NACK == cfg->danger_mode ))
   {
#ifdef MIN_RUN_EVERY
      /* Test for *slightly* less than a second for those trying to
         introduce skew */
      if ( cfg->run_every < MIN_RUN_EVERY )
      {
         error_msg("DANGER: A sampling period of less than a second was specified without -D!");
         mfail = 1;
      }
#endif

#ifdef MAX_QUAD_COUNT
      /* This really should be for the number of providers, not quads */
      if ( cfg->quad_count >= MAX_QUAD_COUNT )
      {
         error_msg("DANGER: Exceeded safe registered quad count. Acknowledge the danger with -D!");
         mfail = 1;
      }
#endif
   }


   /* Do some substitutions ($ARGx for arg item)
      Note - this is not exceptionally strong but it is what is supported
      at this time.

      What is supported:
      - Only ONE $ARGx per line
      - Only $ARG1 (really 0) through $ARG9
      - Only in a quad string
   */
   ascount = 0;
   pn = cfg->pnlist;
   while ( pn )
   {
      if ( NULL != ( argsub = strstr(pn->quad, "$ARG") ) )
      {
         /* Good news! This is supported */

         /* quad is a string, not a quad! So all insertions are "complex" */
         /* First - Save the leading part (if any) */
         before_arg = NULL;
         if ( argsub != pn->quad )
            before_arg = pn->quad;

         argnum = -1;
         if (( argsub[4] >= '0' ) && ( argsub[4] <= '9' ))
            argnum = argsub[4] - '0';

         after_arg = NULL;
         if (( argsub[5] != 0 ) && ( argnum >= 0 ))
            after_arg = argsub + 5;

         /* Validate that things are correct */
         if ( argnum >= 0 )
         {
            if ( NULL == (argval = GetConfArgument(clo, argnum)) )
            {
               error_msg("ERROR: Argument not supplied for \"$ARG%d\".", argnum);
               mfail = 1;
            }      
            else
            {
               if ( NULL == (rebuilt_arg = (char *)malloc(strlen(pn->quad) + strlen(argval) + 1)) )
               {
                  /* Shine this noise - just exit on the extreme rare case of failrue */
                  error_msg("ERROR: Failed to allocate memory for arg replacement string.");
                  return(1);
               }

               rebuilt_arg[0] = 0;

               i = 0;
               j = 0;
               if ( before_arg )
               {
                  while(before_arg[j] != '$')
                     rebuilt_arg[i++] = before_arg[j++];
               }

               j = 0;
               while(argval[j] != 0)
                  rebuilt_arg[i++] = argval[j++];

               if ( after_arg )
               {
                  j = 0;
                  while(after_arg[j] != 0)
                     rebuilt_arg[i++] = after_arg[j++];
               }

               rebuilt_arg[i] = 0;

               free(pn->quad);
               pn->quad = rebuilt_arg;

               ascount++; /* Keep track of how many successful substitutions done */
            }
         }
         else
         {
            dotdotdot_string(errstr, pn->quad, 35);
            error_msg("ERROR: Failed to parse argument in quad \"%s\".", errstr);
            mfail = 1;
         }
      }

      pn = pn->next;
   }

   /* Activate the data points (but not threads) */
   pn = cfg->pnlist;
   while ( pn )
   {
      if(EnableDataPoint(p, pn))
      {
         dotdotdot_string(errstr, pn->quad, 45);
         error_msg("ERROR: Unable to register \"%s\".", errstr);
         mfail = 1;
      }

      pn = pn->next;
   }

   /* mfail lets errors build up (a bit) before the app bails. This way the
      user can (potentially) diagnose more than one error at a time. */
   if ( mfail )
      return(1);
   
   /* Count the number of active providers */
   if ( 1 > (apcnt = GetActiveProviderCount(p)) )
   {
      error_msg("ERROR: No providers are registered for updates.");
      return(1);
   }

   /* See "danger.h" */
#ifdef MAX_ACTIVE_PROVIDERS
   /* Check again for danger conditions */
   if (( 0 == clo->bDanger ) && ( DANGER_NACK == cfg->danger_mode ))
   {
      if ( apcnt >= MAX_ACTIVE_PROVIDERS )
      {
         error_msg("DANGER: Exceeded safe max provider count. Acknowledge the danger with -D!");
         return(1);
      }      
   }
#endif

   /* Calculate the divisior for per-second averaging */

   if ( cfg->run_every < 950 )
   {
      /* 950 shall be considered 1 second - for those looking to 
         introduce drift. Anything less than that, then no averaging
         is going to happen. (although... concievably.... we could 
         go negative and consider this a multiplier.).    */
      sdivisor = 1;
   }
   else
   {
      stemp = cfg->run_every % 1000;

      if ( stemp >= 950 )
      {
         sdivisor = cfg->run_every + ( 1000 - stemp );
         sdivisor = sdivisor / 1000;
      }
      else if ( stemp <= 50 )
      {
         sdivisor = cfg->run_every - stemp;
         sdivisor = sdivisor / 1000;
      }
      else
      {
         /* Not going to average */
         sdivisor = 1;
      }
   }

   if ( clo->bVerbose )
   {
      provcnt = 0;
      this_provider = p->prov_list;
      while( this_provider )
      {
         provcnt++;
         this_provider = this_provider->next;
      }

      /* This MUST go to stderr - because someone might be capturing stdout */
      fprintf(stderr, "Registered %d providers, %d active.\n", provcnt, apcnt);
      fprintf(stderr, "Requested (pre-enabled) %d quads.\n", cfg->quad_count);
      fprintf(stderr, "Per-Second averaging factor is %d.\n", sdivisor);
      fprintf(stderr, "Completed %d $ARGx substitutions to the config file.\n", ascount);
   }



   /* Set up our thread structures (but not the threads themselves) */
   if ( NULL == ( tr = InitThreadRoot(apcnt, sdivisor) ) )
      return(1);

   /* Commentary: The "hooks" to install the writer modules are not as
         simple as a "point registration". The init must be called, the
         write() must be registered (and then called by a thread) and the
         finish() method must be called on exit - after likely being 
         registered. So the three interfaces are well defined... the 
         problem is that they are defined in very different places/ways.
         Additionally, the idea of calling init() inline is not so brilliant
         as the data then has to be fished out of some struct later in
         main() (as it is about to exit) to call the finish() method.
   */
   /* Start with bad values */
   writer_state = -1;
   writer_data = NULL;

   /* Make the bad values good */
   switch ( cfg->send_to )
   {
   case WM_STDOUT_TYPE:
      writer_data = InitStdoutWM(p, cfg);
      writer_state = SetWriterData(tr, writer_data, StdoutWMWrite, StdoutWMFinish);
      writer_finish = StdoutWMFinish;
      break;
   case WM_FILE_TYPE:
      writer_data = InitFileWM(p, cfg);
      writer_state = SetWriterData(tr, writer_data, WriteFileWM, FinishFileWM);
      writer_finish = FinishFileWM;
      break;
   case WM_ALARM_TYPE:
      writer_data = InitAlarmWM(p, cfg);
      writer_state = SetWriterData(tr, writer_data, WriteAlarmWM, FinishAlarmWM);
      writer_finish = FinishAlarmWM;
      break;
   case WM_BCD_TYPE:
      writer_data = InitBCDWM(p, cfg);
      writer_state = SetWriterData(tr, writer_data, WriteBCDWM, FinishBCDWM);
      writer_finish = FinishBCDWM;
      break;
   default:
      error_msg("ERROR: Internal error send_to type %d unknown.", cfg->send_to);
      break;
   }

   /* Look for bad values */
   if ( NULL == writer_data )
   {
      error_msg("ERROR: Failed to initialize writer module data.");
      return(1);
   }

   if ( 0 != writer_state )
   {
      error_msg("ERROR: Failed to set writer module data.");
      return(1);
   }

   /* This is where we will daemonize. Because:
      - The command line has been parsed (checked for errors)
      - The config file has been parsed (checked for errors)
      - The providers have been registered / validated (checked for errors)
      - The writer has looked at all the options (checked for errors)
      - Only after all of this can we fork() with clarity
      > Also note - we MUST fork() before the thread creation or they will
        be stripped away in the fork().
   */
   if ( cfg->run_method == RM_DAEMON )
   {
      make_daemon();
      /* Set default error message destination to syslog */
      errorto = ERROR_MSG_SYSLOG;
   }

   /* ========== NOW POTENTIALLY A DAEMON ========== */

   /* Lock this - makes the timer hang until the worker is ready */
   pthread_mutex_lock(&tr->wrarg->readygo);

   /* ========== JUST ONE THREAD, ABOUT TO BE MANY ========== */

   /* Spawn the timer thread first - because the launch code also sets
      the signal handling settings that all threads will inherit. If
      this is going to be moved, then the signal handling mask needs
      to be removed from this function. */
   if ( NULL == (timerc = SpawnTimerThread(cfg->run_every)) )
      return(1);

   /* Spawn worker threads */
   hot_provider = GetNextActiveProvider(p, NULL);
   while ( hot_provider )
   {
      if ( SpawnWorkerThread(tr, hot_provider) )
         return(1);

      hot_provider = GetNextActiveProvider(p, hot_provider);
   }

   /* Spawn writer thread LAST - It will release readygo */
   /* The point here is to give te workers every chance to get started
      and wait until the very last minute to spawn the writer thread.
      Because it is the writer thread that will release the readygo
      lock and let things start. While this is not *perfect* (the
      workers *could* be still starting - but that is exceptionally
      unlikely), it is fairly solid (as witnessed in practice). */
   if ( SpawnWriterThread(tr) )
      return(1);

   /* If the user said run for x time, then set that up here */
   stop_at = time(NULL);
   stop_at--;            /* Effectively an assert(), but more about
                            making the compiler happy. */

   if ( 0 < cfg->run_for )
   {
      stop_at = time(NULL);
      stop_at += cfg->run_for;
   }


   /* This is the timer loop that activates all the other threads */
   first_iteration = 1;
   while(go)
   {
      /* Check for run_for time expiration */
      if ( 0 < cfg->run_for )
      {
         time_now = time(NULL);
         if ( time_now >= stop_at )
         {
            go = 0;
            continue;
         }
      }

      /* The first iteration is used to avoid printing data on start
         that is typically incomplete anyways. (Incomplete = the diff
         values are not properly timed) Also, the first printing is
         timed VERY CLOSE to the second iteration. So it is ok to 
         skip this. Unfortunately, the way the loop is structured the
         timer (event) has to happen at the BOTTOM so that we can exit
         out (without some kind of break) when we get our event. The
         break *may* have been the more elegant answer here....
      */
      if ( first_iteration )
         first_iteration = 0;
      else
      {
         pthread_mutex_lock(&tr->wrarg->readygo); /* Gotta take lock to go */

         tc = 0;
         while ( tc < apcnt )
         {
            pthread_cond_signal(&tr->wkalist[tc].runcond);
            tc++;
         }

         pthread_cond_signal(&tr->wrarg->writecond);
      }

      /* What is going on here:
         - There is a mutex/cond semaphore that we block on waiting
           for some sort of signal. Typically this will be a simple
           alarm timer, but it may be a Ctrl-C or similarly induced
           signal. The key difference will be what the value of the
           global "go" is. If it is a timer, then go will be 1. If
           it is an exit-inducing event, then go will be 0. Either
           way, go will be evaluated at the top of the loop.
         - No, go is not protected by a mutex. No, this is not seen
           as a problem.
         - The mutex here is only for access to the cond variable.
           It protects nothing (other than the cond).
         - The cond here is about responding to the signal induced
           event loop. And as expressed earlier... there are really
           only two events we care about - a timer tick and a quit
           signal.
       */

      /* Standard cond wait block */
      pthread_mutex_lock(&timerc->mutex);
      while( tt == 0 ) /* Use tt because timer may have already fired */
         pthread_cond_wait(&timerc->cond, &timerc->mutex);
      tt = 0; /* Immediately clear */
      pthread_mutex_unlock(&timerc->mutex);
   }

   /* Take the writer lock (to insure that it is done writing)
      and then finish up the write - whatever that may be. The
      writer_finish() method was registered at about the same time the
      write() method.
   */
   pthread_mutex_lock(&tr->wrarg->writelock);
   writer_finish(tr->wrarg->writer_data);
   return(0);
}
Example #18
0
void cond_signal(cond_t cond) {
  pthread_cond_t *pcond = (pthread_cond_t *)cond;

  int res = pthread_cond_signal(cond);
  CHECK_EQ(res, 0);
}
/*Scheduler input function*/
void auth_mgr_input(nkn_task_id_t id)
{
    nkn_task_set_state(id, TASK_STATE_EVENT_WAIT);
    struct nkn_task     *ntask = nkn_task_get_task(id);
    int dns_type;
    int ret=0;
    char domain_name[2048];
    char *p_domain_name;

    assert(ntask);
    auth_msg_t *data = (auth_msg_t*)nkn_task_get_data(id);
    /* If its DNS lookup, the scheduler thread will just fire this request
    and leave, so no need to put it into a queue like auth tasks*/
    if (data->authtype==DNSLOOKUP)
    {
        if (adnsd_enabled) {
            adns_daemon_input(id);
            return;
        }

        auth_dns_t* pdns=(auth_dns_t*)(data->authdata);
        pdns->auth_task_id=id;
        //Returns void
        pthread_mutex_lock(&cares_mutex);
        AO_fetch_and_add1(&glob_dns_task_called);
        /* Since we will support ttl provided by nameserver
         * we will not be using gethostbyname() anymore
         * Also, I should be using nameser.h and have ns_c_in
         * and ns_t_a for the below query, but lots of woes.
                 * ares_gethostbyname(channel,(char*)pdns->domain,AF_INET,
         *		cares_callback,data);
         */

        /* TODO: use nameser.h */
        if (pdns->ip[0].family == AF_INET) {
            dns_type = 1; // ns_t_a
        } else {
            dns_type = 28; // ns_t_aaaa
        }

        if (pdns->dns_query_len == 0) {
            p_domain_name = (char *)pdns->domain;
        } else {
            memcpy(domain_name, pdns->domain, pdns->domain_len);
            domain_name[pdns->domain_len] = '.';
            memcpy(domain_name + pdns->domain_len + 1, pdns->dns_query, pdns->dns_query_len);
            domain_name[pdns->domain_len + 1 + pdns->dns_query_len] = '\0';
            p_domain_name = domain_name;
        }
        ares_query(channel,
                   p_domain_name,
                   1, /*ns_c_in = 1 Class: Internet. */
                   dns_type,
                   cares_callback_req, data);
        /*
         * Wake up the select loop.
         */
        if (channel_ready == 0) {
            ares_destroy(channel);
            //re-init the channel to get a new port
            ret = ares_init_options(&channel, &options, optmask);
            if (ret != ARES_SUCCESS) {
                DBG_LOG(SEVERE, MOD_AUTHMGR,"ares_init: %d %s", ret, ares_strerror(ret));
                assert(0);
            }
            channel_ready = 1;
            AO_fetch_and_add1(&glob_dns_channel_reinit);
            pthread_mutex_unlock(&cares_mutex);
            return;
        }
        pthread_cond_signal(&cares_cond);
        pthread_mutex_unlock(&cares_mutex);
    }
    else {
        NKN_MUTEX_LOCK(&authreq_mutex);
        if (isam_task_arrFull()) {
            nkn_task_set_action_and_state(id, TASK_ACTION_OUTPUT,
                                          TASK_STATE_RUNNABLE);
            NKN_MUTEX_UNLOCK(&authreq_mutex);
            return;
        }
        auth_task_arr[auth_task_arr_tail] = id;
        if (auth_task_arr_tail == (MAX_AM_TASK_ARR - 1))
        {
            auth_task_arr_tail = 0;
        }
        else
        {
            auth_task_arr_tail++;
        }
        pthread_cond_signal(&authreq_cond);
        NKN_MUTEX_UNLOCK(&authreq_mutex);
    }

    return;
}
Example #20
0
 void unlock()
 {
     pdalboost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
     is_locked=false;
     BOOST_VERIFY(!pthread_cond_signal(&cond));
 }
/*
 * Wakeup the kernel, if sleeping (shall not be called from a signal handler) */
void interrupt(void)
{
    pthread_cond_signal(&wfi_cond);
}
	void ConditionVariableImpl::Signal()
	{
		pthread_cond_signal(&m_cv);
	}
Example #23
0
File: mscli.c Project: bigclean/moc
void mssync_signal(struct mssync *s)
{
    pthread_cond_signal(&(s->cond));
}
/*
 * Function that triggers the broadcasting agent
 * via a mutex.
 * Not intended for direct usage; use wrapper functions instead.
 */
void trigger_broadcast(int type) {
    pthread_mutex_lock(&trigger_mutex);
    broadcast_type = type;
    pthread_cond_signal(&trigger_bcast);
    pthread_mutex_unlock(&trigger_mutex);
}
Example #25
0
void Thread::Resume()
{
  //signal conditional variable;
  int err = pthread_cond_signal(&m_cond);
  if (err) throw HVException("can not signal pthread conditional");
}
Example #26
0
int
pkg_create_repo(char *path, bool force, bool filelist,
		void (progress)(struct pkg *pkg, void *data), void *data)
{
	FTS *fts = NULL;
	struct thd_data thd_data;
	int num_workers;
	size_t len;
	pthread_t *tids = NULL;
	struct digest_list_entry *dlist = NULL, *cur_dig, *dtmp;
	sqlite3 *sqlite = NULL;

	char *errmsg = NULL;
	int retcode = EPKG_OK;

	char *repopath[2];
	char repodb[MAXPATHLEN + 1];
	char repopack[MAXPATHLEN + 1];
	char *manifest_digest;
	FILE *psyml, *fsyml, *mandigests;

	psyml = fsyml = mandigests = NULL;

	if (!is_dir(path)) {
		pkg_emit_error("%s is not a directory", path);
		return (EPKG_FATAL);
	}

	repopath[0] = path;
	repopath[1] = NULL;

	len = sizeof(num_workers);
	if (sysctlbyname("hw.ncpu", &num_workers, &len, NULL, 0) == -1)
		num_workers = 6;

	if ((fts = fts_open(repopath, FTS_PHYSICAL|FTS_NOCHDIR, NULL)) == NULL) {
		pkg_emit_errno("fts_open", path);
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	snprintf(repodb, sizeof(repodb), "%s/%s", path, repo_packagesite_file);
	if ((psyml = fopen(repodb, "w")) == NULL) {
		retcode = EPKG_FATAL;
		goto cleanup;
	}
	if (filelist) {
		snprintf(repodb, sizeof(repodb), "%s/%s", path, repo_filesite_file);
		if ((fsyml = fopen(repodb, "w")) == NULL) {
			retcode = EPKG_FATAL;
			goto cleanup;
		}
	}
	snprintf(repodb, sizeof(repodb), "%s/%s", path, repo_digests_file);
	if ((mandigests = fopen(repodb, "w")) == NULL) {
		retcode = EPKG_FATAL;
		goto cleanup;
	}

	snprintf(repodb, sizeof(repodb), "%s/%s", path, repo_db_file);
	snprintf(repopack, sizeof(repopack), "%s/repo.txz", path);

	pack_extract(repopack, repo_db_file, repodb);

	if ((retcode = pkgdb_repo_open(repodb, force, &sqlite, true)) != EPKG_OK)
		goto cleanup;

	if ((retcode = pkgdb_repo_init(sqlite, true)) != EPKG_OK)
		goto cleanup;

	thd_data.root_path = path;
	thd_data.max_results = num_workers;
	thd_data.num_results = 0;
	thd_data.stop = false;
	thd_data.fts = fts;
	thd_data.read_files = filelist;
	pthread_mutex_init(&thd_data.fts_m, NULL);
	thd_data.results = NULL;
	thd_data.thd_finished = 0;
	pthread_mutex_init(&thd_data.results_m, NULL);
	pthread_cond_init(&thd_data.has_result, NULL);
	pthread_cond_init(&thd_data.has_room, NULL);

	/* Launch workers */
	tids = calloc(num_workers, sizeof(pthread_t));
	for (int i = 0; i < num_workers; i++) {
		pthread_create(&tids[i], NULL, (void *)&read_pkg_file, &thd_data);
	}

	for (;;) {
		struct pkg_result *r;
		const char *origin;

		long manifest_pos, files_pos;

		pthread_mutex_lock(&thd_data.results_m);
		while ((r = thd_data.results) == NULL) {
			if (thd_data.thd_finished == num_workers) {
				break;
			}
			pthread_cond_wait(&thd_data.has_result, &thd_data.results_m);
		}
		if (r != NULL) {
			LL_DELETE(thd_data.results, thd_data.results);
			thd_data.num_results--;
			pthread_cond_signal(&thd_data.has_room);
		}
		pthread_mutex_unlock(&thd_data.results_m);
		if (r == NULL) {
			break;
		}

		if (r->retcode != EPKG_OK) {
			continue;
		}

		/* do not add if package if already in repodb
		   (possibly at a different pkg_path) */

		retcode = pkgdb_repo_cksum_exists(sqlite, r->cksum);
		if (retcode == EPKG_FATAL) {
			goto cleanup;
		}
		else if (retcode == EPKG_OK) {
			continue;
		}

		if (progress != NULL)
			progress(r->pkg, data);

		manifest_pos = ftell(psyml);
		pkg_emit_manifest_file(r->pkg, psyml, PKG_MANIFEST_EMIT_COMPACT, &manifest_digest);
		if (filelist) {
			files_pos = ftell(fsyml);
			pkg_emit_filelist(r->pkg, fsyml);
		} else {
			files_pos = 0;
		}

		pkg_get(r->pkg, PKG_ORIGIN, &origin);

		cur_dig = malloc(sizeof (struct digest_list_entry));
		cur_dig->origin = strdup(origin);
		cur_dig->digest = manifest_digest;
		cur_dig->manifest_pos = manifest_pos;
		cur_dig->files_pos = files_pos;
		LL_PREPEND(dlist, cur_dig);

		retcode = pkgdb_repo_add_package(r->pkg, r->path, sqlite,
				manifest_digest, false, true);
		if (retcode == EPKG_END) {
			continue;
		}
		else if (retcode != EPKG_OK) {
			goto cleanup;
		}

		pkg_free(r->pkg);
		free(r);
	}

	/* Now sort all digests */
	LL_SORT(dlist, digest_sort_compare_func);
cleanup:
	if (pkgdb_repo_close(sqlite, retcode == EPKG_OK) != EPKG_OK) {
		retcode = EPKG_FATAL;
	}
	LL_FOREACH_SAFE(dlist, cur_dig, dtmp) {
		if (retcode == EPKG_OK) {
			fprintf(mandigests, "%s:%s:%ld:%ld\n", cur_dig->origin,
				cur_dig->digest, cur_dig->manifest_pos, cur_dig->files_pos);
		}
		free(cur_dig->digest);
		free(cur_dig->origin);
		free(cur_dig);
	}
	if (tids != NULL) {
		// Cancel running threads
		if (retcode != EPKG_OK) {
			pthread_mutex_lock(&thd_data.fts_m);
			thd_data.stop = true;
			pthread_mutex_unlock(&thd_data.fts_m);
		}
		// Join on threads to release thread IDs
		for (int i = 0; i < num_workers; i++) {
			pthread_join(tids[i], NULL);
		}
		free(tids);
	}

	if (fts != NULL)
		fts_close(fts);

	if (fsyml != NULL)
		fclose(fsyml);

	if (psyml != NULL)
		fclose(psyml);

	if (mandigests != NULL)
		fclose(mandigests);

	if (sqlite != NULL)
		sqlite3_close(sqlite);

	if (errmsg != NULL)
		sqlite3_free(errmsg);

	sqlite3_shutdown();

	return (retcode);
}
Example #27
0
static void ghbn_signal(rktio_t *rktio)
{
  pthread_cond_signal(&rktio->ghbn_start);
}
Example #28
0
void
read_pkg_file(void *data)
{
	struct thd_data *d = (struct thd_data*) data;
	struct pkg_result *r;
	struct pkg_manifest_key *keys = NULL;

	FTSENT *fts_ent = NULL;
	char fts_accpath[MAXPATHLEN + 1];
	char fts_path[MAXPATHLEN + 1];
	char fts_name[MAXPATHLEN + 1];
	off_t st_size;
	int fts_info, flags;

	char *ext = NULL;
	char *pkg_path;

	pkg_manifest_keys_new(&keys);

	for (;;) {
		fts_ent = NULL;

		/*
		 * Get a file to read from.
		 * Copy the data we need from the fts entry localy because as soon as
		 * we unlock the fts_m mutex, we can not access it.
		 */
		pthread_mutex_lock(&d->fts_m);
		if (!d->stop)
			fts_ent = fts_read(d->fts);
		if (fts_ent != NULL) {
			strlcpy(fts_accpath, fts_ent->fts_accpath, sizeof(fts_accpath));
			strlcpy(fts_path, fts_ent->fts_path, sizeof(fts_path));
			strlcpy(fts_name, fts_ent->fts_name, sizeof(fts_name));
			st_size = fts_ent->fts_statp->st_size;
			fts_info = fts_ent->fts_info;
		}
		pthread_mutex_unlock(&d->fts_m);

		// There is no more jobs, exit the main loop.
		if (fts_ent == NULL)
			break;

		/* skip everything that is not a file */
		if (fts_info != FTS_F)
			continue;

		ext = strrchr(fts_name, '.');

		if (ext == NULL)
			continue;

		if (strcmp(ext, ".tgz") != 0 &&
				strcmp(ext, ".tbz") != 0 &&
				strcmp(ext, ".txz") != 0 &&
				strcmp(ext, ".tar") != 0)
			continue;

		*ext = '\0';

		if (strcmp(fts_name, repo_db_archive) == 0 ||
			strcmp(fts_name, repo_packagesite_archive) == 0 ||
			strcmp(fts_name, repo_filesite_archive) == 0 ||
			strcmp(fts_name, repo_digests_archive) == 0)
			continue;
		*ext = '.';

		pkg_path = fts_path;
		pkg_path += strlen(d->root_path);
		while (pkg_path[0] == '/')
			pkg_path++;

		r = calloc(1, sizeof(struct pkg_result));
		strlcpy(r->path, pkg_path, sizeof(r->path));

		if (d->read_files)
			flags = PKG_OPEN_MANIFEST_ONLY;
		else
			flags = PKG_OPEN_MANIFEST_ONLY | PKG_OPEN_MANIFEST_COMPACT;

		if (pkg_open(&r->pkg, fts_accpath, keys, flags) != EPKG_OK) {
			r->retcode = EPKG_WARN;
		} else {
			sha256_file(fts_accpath, r->cksum);
			pkg_set(r->pkg, PKG_CKSUM, r->cksum,
			    PKG_REPOPATH, pkg_path,
			    PKG_PKGSIZE, st_size);
		}


		/* Add result to the FIFO and notify */
		pthread_mutex_lock(&d->results_m);
		while (d->num_results >= d->max_results) {
			pthread_cond_wait(&d->has_room, &d->results_m);
		}
		LL_APPEND(d->results, r);
		d->num_results++;
		pthread_cond_signal(&d->has_result);
		pthread_mutex_unlock(&d->results_m);
	}

	/*
	 * This thread is about to exit.
	 * Notify the main thread that we are done.
	 */
	pthread_mutex_lock(&d->results_m);
	d->thd_finished++;
	pthread_cond_signal(&d->has_result);
	pthread_mutex_unlock(&d->results_m);
	pkg_manifest_keys_free(keys);
}
Example #29
0
//取连接  
T_Connect * get_SC_connect(int TCBno,int n,int flg)
{
int i,num;
pool *pl;
resource *rs;
pthread_t tid=pthread_self();

	if(!scpool || n<0 || n>=SCPOOLNUM) return NULL;
	pl=&scpool[n];
	if(!pl->lnk) {
		ShowLog(1,"%s:无效的连接池[%d]",__FUNCTION__,n);
		return (T_Connect *)-1;
	}
	num=pl->resource_num;
	if(0!=pthread_mutex_lock(&pl->mut)) return (T_Connect *)-1;
    while(1) {
	i=get_lnk_no(pl);
	if(i>=0) {
		rs=&pl->lnk[i];
		if(rs->Conn.Socket<0 || rs->cli.Errno<0) {
			switch(sc_connect(pl,rs)) {
			case -1:
			case -2:
			case -3:
				ShowLog(1,"%s:scpool[%d].%d 连接%s/%s错:err=%d,%s",
					__FUNCTION__,n,i,pl->log.HOST,pl->log.PORT,
					rs->cli.Errno, rs->cli.ErrMsg); 
				add_lnk(pl,i);
				pthread_mutex_unlock(&pl->mut);
				return (T_Connect *)-1;
			case 0:
				break;
			default:
				rs->cli.Errno=-1;
				ShowLog(1,"%s:scpool[%d].%d 连接%s/%s错:err=%d,%s",
					__FUNCTION__,n,i,pl->log.HOST,pl->log.PORT,
					rs->cli.Errno, rs->cli.ErrMsg);
				add_lnk(pl,i);
				continue;
			} 
		} 
		rs->TCB_q[rs->tcb_num++]=TCBno;
		rs->timestamp=now_usec();
		if(rs->tcb_num < TCBNUM) {
			add_lnk(pl,i);
			pthread_cond_signal(&pl->cond); //如果有等待连接的线程就唤醒它 
		}
		pthread_mutex_unlock(&pl->mut);
		if(log_level) ShowLog(log_level,"%s tid=%lu,TCB:%d,pool[%d].lnk[%d]",__FUNCTION__,
			tid,TCBno,n,i);
		rs->cli.Errno=0;
		*rs->cli.ErrMsg=0;
		return &rs->Conn;
	}
	if(flg) {	//flg !=0,don't wait
		pthread_mutex_unlock(&pl->mut);
		return NULL;
	}
	if(log_level) ShowLog(log_level,"%s tid=%lu pool[%d] suspend",__FUNCTION__,pthread_self(),n);
	pthread_cond_wait(&pl->cond,&pl->mut); //没有资源,等待 
	if(log_level) ShowLog(log_level,"%s tid=%lu pool[%d] weakup",__FUNCTION__,pthread_self(),n);
    }
}
Example #30
0
void* worker(void* x)
{
	int id = *((int *) x), i, current=-1;
	element* me = &workers[id-1];
	queueReceived terminated;
	received *term;
	
	#ifdef DEBUG
		printf("[DEBUG] THREAD%d is now working\n", id);
	#endif
	
	queueReceived_init(&terminated);
	
	while(1)
	{
		pthread_mutex_lock(&me->mutex);
		if (me->q.head == NULL)
		{
			pthread_cond_wait(&me->work, &me->mutex);
		}
		pthread_mutex_unlock(&me->mutex);
		
		pthread_mutex_lock(&pikachu);
		if (toShutdown)
		{
			pthread_mutex_unlock(&pikachu);
			#ifdef DEBUG
				pthread_mutex_lock(&display);
					printf("[DEBUG] worker thread%d killed\n", id);
				pthread_mutex_unlock(&display);
			#endif
			
			for (i=0 ; i<N_WORKERS ; i++)
				pthread_cond_signal(&workers[i].work);
			
			pthread_exit(0);
		}
		pthread_mutex_unlock(&pikachu);
		
		pthread_mutex_lock(&me->mutex);
		while (me->q.head)
		{
			term = getJob(me->q.head->id, &terminated);
			
			if (term == NULL)
			{
				term = received_init();
				enqueueReceived(&terminated, term);
			}
			
			segment* s = dequeue(&me->q);
			if (s->last)
				term->ended = true;
			enqueue(&term->q, s);
		}
		pthread_mutex_unlock(&me->mutex);
		
		for (term=terminated.head ; term ; term=term->next)
		{
			if(term->ended && term->q.head)
			{
				pthread_mutex_lock(&display);
				printf("\n\n[THREAD%d] JOB %d\n", id, term->q.head->id);
				while (term->q.head)
				{
					segment* s = dequeue(&term->q);
					if (s->page != current)
					{
						current = s->page;
						printf("PAGE %d\n", current);
					}
					printf("%s\n", s->text);
				}
				pthread_mutex_unlock(&display);
			}
		}
	}
	pthread_exit(0);
}